blob: 8d390fd6be7e528b4e7a60e43d5752898475a96d [file] [log] [blame]
// Copyright 2015 The Chromium 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 serialization
import (
"bytes"
"compress/gzip"
"encoding/base64"
"fmt"
"io/ioutil"
"mojo/public/go/bindings"
"mojom/generated/mojom_files"
"mojom/generated/mojom_types"
"mojom/mojom_tool/mojom"
"mojom/mojom_tool/parser"
"reflect"
"testing"
myfmt "third_party/golang/src/fmt"
)
// singleFileTestCase stores the data for one serialization test case
// in which only a single file is added to the file graph.
type singleFileTestCase struct {
fileName string
mojomContents string
lineAndcolumnNumbers bool
expectedFile *mojom_files.MojomFile
expectedGraph *mojom_files.MojomFileGraph
}
// singleFileTest contains a series of singleFileTestCase and a current
// testCaseNum.
type singleFileTest struct {
cases []singleFileTestCase
testCaseNum int
}
// expectedFile() returns the expectedFile of the current test case.
func (t *singleFileTest) expectedFile() *mojom_files.MojomFile {
return t.cases[t.testCaseNum].expectedFile
}
// expectedGraph() returns the expectedGraph of the current test case.
func (t *singleFileTest) expectedGraph() *mojom_files.MojomFileGraph {
return t.cases[t.testCaseNum].expectedGraph
}
// fileName() returns the fileName of the current test case
func (t *singleFileTest) fileName() string {
return t.cases[t.testCaseNum].fileName
}
// addTestCase() should be invoked at the start of a case in
// TestSingleFileSerialization.
func (test *singleFileTest) addTestCase(moduleNameSpace, contents string) {
fileName := fmt.Sprintf("file%d", test.testCaseNum)
test.cases = append(test.cases, singleFileTestCase{fileName, contents, false,
new(mojom_files.MojomFile), new(mojom_files.MojomFileGraph)})
test.expectedFile().FileName = fileName
test.expectedFile().SpecifiedFileName = stringPointer(fileName)
test.expectedFile().ModuleNamespace = &moduleNameSpace
test.expectedGraph().ResolvedTypes = make(map[string]mojom_types.UserDefinedType)
test.expectedGraph().ResolvedConstants = make(map[string]mojom_types.DeclaredConstant)
}
// endTestCase() should be invoked at the end of a case in
// TestSingleFileSerialization.
func (test *singleFileTest) endTestCase() {
test.expectedGraph().Files = make(map[string]mojom_files.MojomFile)
test.expectedGraph().Files[test.fileName()] = *test.expectedFile()
test.testCaseNum += 1
}
// newShortDeclDataO constructs a new DeclarationData with the given data.
func (test *singleFileTest) newShortDeclData(shortName string) *mojom_types.DeclarationData {
declData := test.newContainedDeclData(shortName, "", nil)
declData.FullIdentifier = nil
return declData
}
// newShortDeclDataO constructs a new DeclarationData with the given data.
func (test *singleFileTest) newShortDeclDataO(declarationOrder, declaredOrdinal int32, shortName string) *mojom_types.DeclarationData {
declData := test.newContainedDeclDataA(declarationOrder, declaredOrdinal, shortName, "", nil, nil)
declData.FullIdentifier = nil
return declData
}
// newDeclData constructs a new DeclarationData with the given data.
func (test *singleFileTest) newDeclData(shortName, fullIdentifier string) *mojom_types.DeclarationData {
return test.newContainedDeclData(shortName, fullIdentifier, nil)
}
// newDeclData constructs a new DeclarationData with the given data.
func (test *singleFileTest) newDeclDataO(declarationOrder, declaredOrdinal int32, shortName, fullIdentifier string) *mojom_types.DeclarationData {
return test.newContainedDeclDataA(declarationOrder, declaredOrdinal, shortName, fullIdentifier, nil, nil)
}
// newDeclDataA constructs a new DeclarationData with the given data, including attributes.
func (test *singleFileTest) newDeclDataA(shortName, fullIdentifier string,
attributes *[]mojom_types.Attribute) *mojom_types.DeclarationData {
return test.newContainedDeclDataA(-1, -1, shortName, fullIdentifier, nil, attributes)
}
// newShortDeclDataA constructs a new DeclarationData with the given data, including attributes.
func (test *singleFileTest) newShortDeclDataA(shortName string,
attributes *[]mojom_types.Attribute) *mojom_types.DeclarationData {
declData := test.newContainedDeclDataA(-1, -1, shortName, "", nil, attributes)
declData.FullIdentifier = nil
return declData
}
// newShortDeclDataA constructs a new DeclarationData with the given data, including attributes.
func (test *singleFileTest) newShortDeclDataAO(declarationOrder, declaredOrdinal int32, shortName string,
attributes *[]mojom_types.Attribute) *mojom_types.DeclarationData {
declData := test.newContainedDeclDataA(declarationOrder, declaredOrdinal, shortName, "", nil, attributes)
declData.FullIdentifier = nil
return declData
}
// newContainedDeclData constructs a new DeclarationData with the given data.
func (test *singleFileTest) newContainedDeclData(shortName, fullIdentifier string, containerTypeKey *string) *mojom_types.DeclarationData {
return test.newContainedDeclDataA(-1, -1, shortName, fullIdentifier, containerTypeKey, nil)
}
// newContainedDeclDataA constructs a new DeclarationData with the given data, including attributes.
func (test *singleFileTest) newContainedDeclDataA(declarationOrder, declaredOrdinal int32, shortName, fullIdentifier string,
containerTypeKey *string, attributes *[]mojom_types.Attribute) *mojom_types.DeclarationData {
return newContainedDeclDataA(declarationOrder, declaredOrdinal, test.fileName(), shortName, fullIdentifier, containerTypeKey, attributes)
}
// newDeclData constructs a new DeclarationData with the given data.
func newDeclData(fileName, shortName, fullIdentifier string) *mojom_types.DeclarationData {
return newContainedDeclData(fileName, shortName, fullIdentifier, nil)
}
// newDeclData constructs a new DeclarationData with the given data.
func newDeclDataO(declarationOrder, declaredOrdinal int32, fileName, shortName, fullIdentifier string) *mojom_types.DeclarationData {
return newContainedDeclDataA(declarationOrder, declaredOrdinal, fileName, shortName, fullIdentifier, nil, nil)
}
// newDeclDataA constructs a new DeclarationData with the given data, including attributes.
func newDeclDataA(fileName, shortName, fullIdentifier string,
attributes *[]mojom_types.Attribute) *mojom_types.DeclarationData {
return newContainedDeclDataA(-1, -1, fileName, shortName, fullIdentifier, nil, attributes)
}
// newContainedDeclData constructs a new DeclarationData with the given data.
func newContainedDeclData(fileName, shortName, fullIdentifier string, containerTypeKey *string) *mojom_types.DeclarationData {
return newContainedDeclDataA(-1, -1, fileName, shortName, fullIdentifier, containerTypeKey, nil)
}
// newContainedDeclDataA constructs a new DeclarationData with the given data, including attributes.
func newContainedDeclDataA(declarationOrder, declaredOrdinal int32, fileName, shortName, fullIdentifier string,
containerTypeKey *string, attributes *[]mojom_types.Attribute) *mojom_types.DeclarationData {
var fullyQualifiedName *string
if fullIdentifier != "" {
fullyQualifiedName = &fullIdentifier
}
return &mojom_types.DeclarationData{
Attributes: attributes,
ShortName: &shortName,
FullIdentifier: fullyQualifiedName,
DeclaredOrdinal: declaredOrdinal,
DeclarationOrder: declarationOrder,
ContainerTypeKey: containerTypeKey,
SourceFileInfo: &mojom_types.SourceFileInfo{
FileName: fileName,
}}
}
// TestSingleFileSerialization uses a series of test cases in which the text of a .mojom
// file is specified and the expected MojomFileGraph is specified using Go struct literals.
func TestSingleFileSerialization(t *testing.T) {
test := singleFileTest{}
////////////////////////////////////////////////////////////
// Test Case: struct field ordinals
////////////////////////////////////////////////////////////
{
contents := `
struct Foo{
int32 x@2;
int32 y@3;
int32 z@0;
int32 w@1;
};`
test.addTestCase("", contents)
// DeclaredMojomObjects
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:Foo"}
// ResolvedTypes
// struct Foo
test.expectedGraph().ResolvedTypes["TYPE_KEY:Foo"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: test.newDeclData("Foo", "Foo"),
Fields: []mojom_types.StructField{
// The fields are in ordinal order and the first two arguments to newShortDeclDataO() are
// declarationOrder and declaredOrdinal.
// field z
{
DeclData: test.newShortDeclDataO(2, 0, "z"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
},
// field w
{
DeclData: test.newShortDeclDataO(3, 1, "w"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
},
// field x
{
DeclData: test.newShortDeclDataO(0, 2, "x"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
},
// field y
{
DeclData: test.newShortDeclDataO(1, 3, "y"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: struct field ordinals, some implicit
////////////////////////////////////////////////////////////
{
contents := `
struct Foo{
int32 x@2;
int32 y;
int32 z@0;
int32 w;
};`
test.addTestCase("", contents)
// DeclaredMojomObjects
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:Foo"}
// ResolvedTypes
// struct Foo
test.expectedGraph().ResolvedTypes["TYPE_KEY:Foo"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: test.newDeclData("Foo", "Foo"),
Fields: []mojom_types.StructField{
// The fields are in ordinal order and the first two arguments to newShortDeclDataO() are
// declarationOrder and declaredOrdinal.
// field z
{
DeclData: test.newShortDeclDataO(2, 0, "z"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
},
// field w
{
DeclData: test.newShortDeclDataO(3, -1, "w"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
},
// field x
{
DeclData: test.newShortDeclDataO(0, 2, "x"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
},
// field y
{
DeclData: test.newShortDeclDataO(1, -1, "y"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: union field tags
////////////////////////////////////////////////////////////
{
contents := `
union Foo{
int32 x@21;
string y@32;
bool z@6;
float w@17;
};`
test.addTestCase("", contents)
// DeclaredMojomObjects
test.expectedFile().DeclaredMojomObjects.Unions = &[]string{"TYPE_KEY:Foo"}
// ResolvedTypes
// union Foo
test.expectedGraph().ResolvedTypes["TYPE_KEY:Foo"] = &mojom_types.UserDefinedTypeUnionType{mojom_types.MojomUnion{
DeclData: test.newDeclData("Foo", "Foo"),
Fields: []mojom_types.UnionField{
// The fields are in tag order and the first two arguments to newShortDeclDataO() are
// declarationOrder and declaredOrdinal.
// field z
{
DeclData: test.newShortDeclDataO(2, 6, "z"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Tag: 6,
},
// field w
{
DeclData: test.newShortDeclDataO(3, 17, "w"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Float},
Tag: 17,
},
// field x
{
DeclData: test.newShortDeclDataO(0, 21, "x"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Tag: 21,
},
// field y
{
DeclData: test.newShortDeclDataO(1, 32, "y"),
Type: &mojom_types.TypeStringType{mojom_types.StringType{false}},
Tag: 32,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: union field tags, some implicit
////////////////////////////////////////////////////////////
{
contents := `
union Foo{
int32 x@21;
string y;
bool z@6;
float w;
};`
test.addTestCase("", contents)
// DeclaredMojomObjects
test.expectedFile().DeclaredMojomObjects.Unions = &[]string{"TYPE_KEY:Foo"}
// ResolvedTypes
// union Foo
test.expectedGraph().ResolvedTypes["TYPE_KEY:Foo"] = &mojom_types.UserDefinedTypeUnionType{mojom_types.MojomUnion{
DeclData: test.newDeclData("Foo", "Foo"),
Fields: []mojom_types.UnionField{
// The fields are in tag order and the first two arguments to newShortDeclDataO() are
// declarationOrder and declaredOrdinal.
// field z
{
DeclData: test.newShortDeclDataO(2, 6, "z"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Tag: 6,
},
// field w
{
DeclData: test.newShortDeclDataO(3, -1, "w"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Float},
Tag: 7,
},
// field x
{
DeclData: test.newShortDeclDataO(0, 21, "x"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Tag: 21,
},
// field y
{
DeclData: test.newShortDeclDataO(1, -1, "y"),
Type: &mojom_types.TypeStringType{mojom_types.StringType{false}},
Tag: 22,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: array of int32
////////////////////////////////////////////////////////////
{
contents := `
struct Foo{
array<int32> bar1;
array<int32, 7> bar2;
array<int32>? bar3;
array<int32, 8>? bar4;
};`
test.addTestCase("", contents)
// DeclaredMojomObjects
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:Foo"}
// ResolvedTypes
// struct Foo
test.expectedGraph().ResolvedTypes["TYPE_KEY:Foo"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: test.newDeclData("Foo", "Foo"),
Fields: []mojom_types.StructField{
// field bar1 is not nullable and not fixed length
{
DeclData: test.newShortDeclDataO(0, -1, "bar1"),
Type: &mojom_types.TypeArrayType{mojom_types.ArrayType{
false, -1, &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32}}},
},
// field bar2 is not nullable and fixed length of 7
{
DeclData: test.newShortDeclDataO(1, -1, "bar2"),
Type: &mojom_types.TypeArrayType{mojom_types.ArrayType{
false, 7, &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32}}},
},
// field bar3 is nullable and not fixed length
{
DeclData: test.newShortDeclDataO(2, -1, "bar3"),
Type: &mojom_types.TypeArrayType{mojom_types.ArrayType{
true, -1, &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32}}},
},
// field bar4 is nullable and fixed length of 8
{
DeclData: test.newShortDeclDataO(3, -1, "bar4"),
Type: &mojom_types.TypeArrayType{mojom_types.ArrayType{
true, 8, &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32}}},
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: map string to int32
////////////////////////////////////////////////////////////
{
contents := `
struct Foo{
map<string, int32> bar1;
map<string?, int32> bar2;
map<string, int32>? bar3;
map<string?, int32>? bar4;
};`
test.addTestCase("", contents)
// DeclaredMojomObjects
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:Foo"}
// ResolvedTypes
// struct Foo
test.expectedGraph().ResolvedTypes["TYPE_KEY:Foo"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: test.newDeclData("Foo", "Foo"),
Fields: []mojom_types.StructField{
// field bar1 is non-nullable with a non-nullable key.
{
DeclData: test.newShortDeclDataO(0, -1, "bar1"),
Type: &mojom_types.TypeMapType{mojom_types.MapType{
false,
&mojom_types.TypeStringType{mojom_types.StringType{false}},
&mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32}}},
},
// field bar2 is non-nullable with a nullable key.
{
DeclData: test.newShortDeclDataO(1, -1, "bar2"),
Type: &mojom_types.TypeMapType{mojom_types.MapType{
false,
&mojom_types.TypeStringType{mojom_types.StringType{true}},
&mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32}}},
},
// field bar3 is nullable with a non-nullable key.
{
DeclData: test.newShortDeclDataO(2, -1, "bar3"),
Type: &mojom_types.TypeMapType{mojom_types.MapType{
true,
&mojom_types.TypeStringType{mojom_types.StringType{false}},
&mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32}}},
},
// field bar4 is nullable with a nullable key.
{
DeclData: test.newShortDeclDataO(3, -1, "bar4"),
Type: &mojom_types.TypeMapType{mojom_types.MapType{
true,
&mojom_types.TypeStringType{mojom_types.StringType{true}},
&mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32}}},
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: enum value initializer
////////////////////////////////////////////////////////////
{
contents := `
enum Foo{
X0,
X1 = 42,
X2 = X1
};`
test.addTestCase("", contents)
// DeclaredMojomObjects
test.expectedFile().DeclaredMojomObjects.TopLevelEnums = &[]string{"TYPE_KEY:Foo"}
// ResolvedTypes
// enum Foo
test.expectedGraph().ResolvedTypes["TYPE_KEY:Foo"] = &mojom_types.UserDefinedTypeEnumType{mojom_types.MojomEnum{
DeclData: test.newDeclData("Foo", "Foo"),
Values: []mojom_types.EnumValue{
// value X1
mojom_types.EnumValue{
DeclData: test.newDeclData("X0", "Foo.X0"),
IntValue: 0,
},
// value X1
mojom_types.EnumValue{
DeclData: test.newDeclData("X1", "Foo.X1"),
InitializerValue: &mojom_types.ValueLiteralValue{&mojom_types.LiteralValueInt8Value{42}},
IntValue: 42,
},
// value X2
mojom_types.EnumValue{
DeclData: test.newDeclData("X2", "Foo.X2"),
InitializerValue: &mojom_types.ValueEnumValueReference{mojom_types.EnumValueReference{
Identifier: "X1",
EnumTypeKey: "TYPE_KEY:Foo",
EnumValueIndex: 1,
}},
IntValue: 42,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: enum value name is shadowed by local constant declaration.
////////////////////////////////////////////////////////////
{
contents := `
enum Color{
RED, BLUE
};
struct MyStruct {
const Color RED = BLUE;
Color a_color = RED; // This should resolve to the local constant RED.
};`
test.addTestCase("", contents)
// DeclaredMojomObjects
test.expectedFile().DeclaredMojomObjects.TopLevelEnums = &[]string{"TYPE_KEY:Color"}
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:MyStruct"}
// Resolved Constants
// MyStruct.RED
test.expectedGraph().ResolvedConstants["TYPE_KEY:MyStruct.RED"] = mojom_types.DeclaredConstant{
DeclData: *test.newContainedDeclData("RED", "MyStruct.RED", stringPointer("TYPE_KEY:MyStruct")),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("Color"), stringPointer("TYPE_KEY:Color")}},
Value: &mojom_types.ValueEnumValueReference{
mojom_types.EnumValueReference{
Identifier: "BLUE",
EnumTypeKey: "TYPE_KEY:Color",
EnumValueIndex: 1}},
}
// ResolvedTypes
// enum Color
test.expectedGraph().ResolvedTypes["TYPE_KEY:Color"] = &mojom_types.UserDefinedTypeEnumType{mojom_types.MojomEnum{
DeclData: test.newDeclData("Color", "Color"),
Values: []mojom_types.EnumValue{
// value RED
mojom_types.EnumValue{
DeclData: test.newDeclData("RED", "Color.RED"),
IntValue: 0,
},
// value BLUE
mojom_types.EnumValue{
DeclData: test.newDeclData("BLUE", "Color.BLUE"),
IntValue: 1,
},
},
}}
// struct MyStruct
test.expectedGraph().ResolvedTypes["TYPE_KEY:MyStruct"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: &mojom_types.DeclarationData{
ShortName: stringPointer("MyStruct"),
FullIdentifier: stringPointer("MyStruct"),
DeclaredOrdinal: -1,
DeclarationOrder: -1,
SourceFileInfo: &mojom_types.SourceFileInfo{
FileName: test.fileName(),
},
ContainedDeclarations: &mojom_types.ContainedDeclarations{
Constants: &[]string{"TYPE_KEY:MyStruct.RED"}},
},
Fields: []mojom_types.StructField{
// field a_color
{
DeclData: test.newShortDeclDataO(0, -1, "a_color"),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("Color"), stringPointer("TYPE_KEY:Color")}},
DefaultValue: &mojom_types.DefaultFieldValueValue{&mojom_types.ValueConstantReference{
mojom_types.ConstantReference{
Identifier: "RED",
ConstantKey: "TYPE_KEY:MyStruct.RED"}}}, // Note this refers to MyStruct.RED and not Color.RED.
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: In-Out method parameters with the same name.
////////////////////////////////////////////////////////////
{
contents := `
module test;
interface EchoService {
EchoString(string? value) => (string? value);
DelayedEchoString(string? value, int32 millis) => (string? value);
};`
test.addTestCase("test", contents)
// DeclaredMojomObjects
test.expectedFile().DeclaredMojomObjects.Interfaces = &[]string{"TYPE_KEY:test.EchoService"}
// ResolvedTypes
// interface EchoService
test.expectedGraph().ResolvedTypes["TYPE_KEY:test.EchoService"] = &mojom_types.UserDefinedTypeInterfaceType{mojom_types.MojomInterface{
DeclData: test.newDeclData("EchoService", "test.EchoService"),
Methods: map[uint32]mojom_types.MojomMethod{
0: mojom_types.MojomMethod{
DeclData: test.newDeclDataO(0, -1, "EchoString", ""),
Parameters: mojom_types.MojomStruct{
DeclData: test.newDeclData("EchoString-request", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: test.newDeclDataO(0, -1, "value", ""),
Type: &mojom_types.TypeStringType{mojom_types.StringType{true}},
},
},
},
ResponseParams: &mojom_types.MojomStruct{
DeclData: test.newDeclData("EchoString-response", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: test.newDeclDataO(0, -1, "value", ""),
Type: &mojom_types.TypeStringType{mojom_types.StringType{true}},
},
},
},
},
1: mojom_types.MojomMethod{
DeclData: test.newDeclDataO(1, -1, "DelayedEchoString", ""),
Parameters: mojom_types.MojomStruct{
DeclData: test.newDeclData("DelayedEchoString-request", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: test.newDeclDataO(0, -1, "value", ""),
Type: &mojom_types.TypeStringType{mojom_types.StringType{true}},
},
mojom_types.StructField{
DeclData: test.newDeclDataO(1, -1, "millis", ""),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
},
},
},
ResponseParams: &mojom_types.MojomStruct{
DeclData: test.newDeclData("DelayedEchoString-response", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: test.newDeclDataO(0, -1, "value", ""),
Type: &mojom_types.TypeStringType{mojom_types.StringType{true}},
},
},
},
Ordinal: 1,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: Explicit Method Ordinals. Tests the DeclarationOrder field.
////////////////////////////////////////////////////////////
{
contents := `
interface MyInterface {
Method1@1();
Method0@0();
};`
test.addTestCase("", contents)
// DeclaredMojomObjects
test.expectedFile().DeclaredMojomObjects.Interfaces = &[]string{"TYPE_KEY:MyInterface"}
// interface EchoService
test.expectedGraph().ResolvedTypes["TYPE_KEY:MyInterface"] = &mojom_types.UserDefinedTypeInterfaceType{mojom_types.MojomInterface{
DeclData: test.newDeclData("MyInterface", "MyInterface"),
Methods: map[uint32]mojom_types.MojomMethod{
0: mojom_types.MojomMethod{
DeclData: test.newDeclDataO(1, 0, "Method0", ""),
Parameters: mojom_types.MojomStruct{
DeclData: test.newDeclData("Method0-request", ""),
Fields: []mojom_types.StructField{},
},
Ordinal: 0,
},
1: mojom_types.MojomMethod{
DeclData: test.newDeclDataO(0, 1, "Method1", ""),
Parameters: mojom_types.MojomStruct{
DeclData: test.newDeclData("Method1-request", ""),
Fields: []mojom_types.StructField{},
},
Ordinal: 1,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: Use of the ServiceName attribute
////////////////////////////////////////////////////////////
{
contents := `
module test;
[ServiceName = "my.test.EchoService"]
interface EchoService {
EchoString(string? value) => (string? value);
};`
test.addTestCase("test", contents)
// DeclaredMojomObjects
test.expectedFile().DeclaredMojomObjects.Interfaces = &[]string{"TYPE_KEY:test.EchoService"}
// ResolvedTypes
// interface EchoService
test.expectedGraph().ResolvedTypes["TYPE_KEY:test.EchoService"] = &mojom_types.UserDefinedTypeInterfaceType{mojom_types.MojomInterface{
DeclData: test.newDeclDataA("EchoService", "test.EchoService", &[]mojom_types.Attribute{{"ServiceName", &mojom_types.LiteralValueStringValue{"my.test.EchoService"}}}),
ServiceName: stringPointer("my.test.EchoService"),
Methods: map[uint32]mojom_types.MojomMethod{
0: mojom_types.MojomMethod{
DeclData: test.newDeclDataO(0, -1, "EchoString", ""),
Parameters: mojom_types.MojomStruct{
DeclData: test.newDeclData("EchoString-request", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: test.newDeclDataO(0, -1, "value", ""),
Type: &mojom_types.TypeStringType{mojom_types.StringType{true}},
},
},
},
ResponseParams: &mojom_types.MojomStruct{
DeclData: test.newDeclData("EchoString-response", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: test.newDeclDataO(0, -1, "value", ""),
Type: &mojom_types.TypeStringType{mojom_types.StringType{true}},
},
},
},
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: Integer constants
////////////////////////////////////////////////////////////
{
contents := `
const uint8 xu8 = 255;
const int8 x8 = -127;
const uint16 xu16 = 0xFFFF;
const int16 x16 = -0x7FFF;
const uint32 xu32 = 4294967295;
const int32 x32 = -2147483647;
const uint64 xu64 = 0xFFFFFFFFFFFFFFFF;
const int64 x64 = -0x7FFFFFFFFFFFFFFF;
`
test.addTestCase("", contents)
// DeclaredMojomObjects
test.expectedFile().DeclaredMojomObjects.TopLevelConstants = &[]string{
"TYPE_KEY:xu8", "TYPE_KEY:x8", "TYPE_KEY:xu16", "TYPE_KEY:x16",
"TYPE_KEY:xu32", "TYPE_KEY:x32", "TYPE_KEY:xu64", "TYPE_KEY:x64"}
// Resolved Values
// xu8
test.expectedGraph().ResolvedConstants["TYPE_KEY:xu8"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("xu8", "xu8"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Uint8},
Value: &mojom_types.ValueLiteralValue{&mojom_types.LiteralValueUint8Value{255}},
}
// x8
test.expectedGraph().ResolvedConstants["TYPE_KEY:x8"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("x8", "x8"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int8},
Value: &mojom_types.ValueLiteralValue{&mojom_types.LiteralValueInt8Value{-127}},
}
// xu16
test.expectedGraph().ResolvedConstants["TYPE_KEY:xu16"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("xu16", "xu16"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Uint16},
Value: &mojom_types.ValueLiteralValue{&mojom_types.LiteralValueUint16Value{0xFFFF}},
}
// x16
test.expectedGraph().ResolvedConstants["TYPE_KEY:x16"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("x16", "x16"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int16},
Value: &mojom_types.ValueLiteralValue{&mojom_types.LiteralValueInt16Value{-0x7FFF}},
}
// xu32
test.expectedGraph().ResolvedConstants["TYPE_KEY:xu32"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("xu32", "xu32"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Uint32},
Value: &mojom_types.ValueLiteralValue{&mojom_types.LiteralValueUint32Value{4294967295}},
}
// x32
test.expectedGraph().ResolvedConstants["TYPE_KEY:x32"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("x32", "x32"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Value: &mojom_types.ValueLiteralValue{&mojom_types.LiteralValueInt32Value{-2147483647}},
}
// xu64
test.expectedGraph().ResolvedConstants["TYPE_KEY:xu64"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("xu64", "xu64"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Uint64},
Value: &mojom_types.ValueLiteralValue{&mojom_types.LiteralValueUint64Value{0xFFFFFFFFFFFFFFFF}},
}
// x64
test.expectedGraph().ResolvedConstants["TYPE_KEY:x64"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("x64", "x64"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int64},
Value: &mojom_types.ValueLiteralValue{&mojom_types.LiteralValueInt64Value{-0x7FFFFFFFFFFFFFFF}},
}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: Builtin Floating-Point Constants
////////////////////////////////////////////////////////////
{
contents := `
const float f1 = float.INFINITY;
const float f2 = float.NEGATIVE_INFINITY;
const float f3 = float.NAN;
const double d1 = double.INFINITY;
const double d2 = double.NEGATIVE_INFINITY;
const double d3 = double.NAN;
`
test.addTestCase("", contents)
// DeclaredMojomObjects
test.expectedFile().DeclaredMojomObjects.TopLevelConstants = &[]string{
"TYPE_KEY:f1", "TYPE_KEY:f2", "TYPE_KEY:f3", "TYPE_KEY:d1", "TYPE_KEY:d2", "TYPE_KEY:d3"}
// Resolved Values
// f1
test.expectedGraph().ResolvedConstants["TYPE_KEY:f1"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("f1", "f1"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Float},
Value: &mojom_types.ValueBuiltinValue{mojom_types.BuiltinConstantValue_FloatInfinity},
}
// f2
test.expectedGraph().ResolvedConstants["TYPE_KEY:f2"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("f2", "f2"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Float},
Value: &mojom_types.ValueBuiltinValue{mojom_types.BuiltinConstantValue_FloatNegativeInfinity},
}
// f3
test.expectedGraph().ResolvedConstants["TYPE_KEY:f3"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("f3", "f3"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Float},
Value: &mojom_types.ValueBuiltinValue{mojom_types.BuiltinConstantValue_FloatNan},
}
// d1
test.expectedGraph().ResolvedConstants["TYPE_KEY:d1"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("d1", "d1"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Double},
Value: &mojom_types.ValueBuiltinValue{mojom_types.BuiltinConstantValue_DoubleInfinity},
}
// d2
test.expectedGraph().ResolvedConstants["TYPE_KEY:d2"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("d2", "d2"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Double},
Value: &mojom_types.ValueBuiltinValue{mojom_types.BuiltinConstantValue_DoubleNegativeInfinity},
}
// d3
test.expectedGraph().ResolvedConstants["TYPE_KEY:d3"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("d3", "d3"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Double},
Value: &mojom_types.ValueBuiltinValue{mojom_types.BuiltinConstantValue_DoubleNan},
}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: Constants defined in terms of other constants.
////////////////////////////////////////////////////////////
{
contents := `
enum Color{
RED, BLUE
};
const int32 x1 = 42;
const int32 x2 = x1;
const int32 x3 = x2;
const Color c1 = RED;
const Color c2 = c1;
const Color c3 = c2;
`
test.addTestCase("", contents)
// DeclaredMojomObjects
test.expectedFile().DeclaredMojomObjects.TopLevelEnums = &[]string{"TYPE_KEY:Color"}
test.expectedFile().DeclaredMojomObjects.TopLevelConstants = &[]string{"TYPE_KEY:x1", "TYPE_KEY:x2",
"TYPE_KEY:x3", "TYPE_KEY:c1", "TYPE_KEY:c2", "TYPE_KEY:c3"}
// Resolved Constants
// x1
test.expectedGraph().ResolvedConstants["TYPE_KEY:x1"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("x1", "x1"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Value: &mojom_types.ValueLiteralValue{&mojom_types.LiteralValueInt8Value{42}},
}
// x2
test.expectedGraph().ResolvedConstants["TYPE_KEY:x2"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("x2", "x2"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Value: &mojom_types.ValueConstantReference{mojom_types.ConstantReference{
Identifier: "x1",
ConstantKey: "TYPE_KEY:x1"}},
ResolvedConcreteValue: &mojom_types.ValueLiteralValue{&mojom_types.LiteralValueInt8Value{42}},
}
// x3
test.expectedGraph().ResolvedConstants["TYPE_KEY:x3"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("x3", "x3"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Value: &mojom_types.ValueConstantReference{mojom_types.ConstantReference{
Identifier: "x2",
ConstantKey: "TYPE_KEY:x2"}},
ResolvedConcreteValue: &mojom_types.ValueLiteralValue{&mojom_types.LiteralValueInt8Value{42}},
}
// c1
test.expectedGraph().ResolvedConstants["TYPE_KEY:c1"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("c1", "c1"),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("Color"), stringPointer("TYPE_KEY:Color")}},
Value: &mojom_types.ValueEnumValueReference{mojom_types.EnumValueReference{
Identifier: "RED",
EnumTypeKey: "TYPE_KEY:Color",
EnumValueIndex: 0}},
}
// c2
test.expectedGraph().ResolvedConstants["TYPE_KEY:c2"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("c2", "c2"),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("Color"), stringPointer("TYPE_KEY:Color")}},
Value: &mojom_types.ValueConstantReference{mojom_types.ConstantReference{
Identifier: "c1",
ConstantKey: "TYPE_KEY:c1"}},
ResolvedConcreteValue: &mojom_types.ValueEnumValueReference{mojom_types.EnumValueReference{
EnumTypeKey: "TYPE_KEY:Color",
EnumValueIndex: 0}},
}
// c3
test.expectedGraph().ResolvedConstants["TYPE_KEY:c3"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("c3", "c3"),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("Color"), stringPointer("TYPE_KEY:Color")}},
Value: &mojom_types.ValueConstantReference{mojom_types.ConstantReference{
Identifier: "c2",
ConstantKey: "TYPE_KEY:c2"}},
ResolvedConcreteValue: &mojom_types.ValueEnumValueReference{mojom_types.EnumValueReference{
EnumTypeKey: "TYPE_KEY:Color",
EnumValueIndex: 0}},
}
// ResolvedTypes
// enum Color
test.expectedGraph().ResolvedTypes["TYPE_KEY:Color"] = &mojom_types.UserDefinedTypeEnumType{mojom_types.MojomEnum{
DeclData: test.newDeclData("Color", "Color"),
Values: []mojom_types.EnumValue{
// value RED
mojom_types.EnumValue{
DeclData: test.newDeclData("RED", "Color.RED"),
IntValue: 0,
},
// value BLUE
mojom_types.EnumValue{
DeclData: test.newDeclData("BLUE", "Color.BLUE"),
IntValue: 1,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case
////////////////////////////////////////////////////////////
{
contents := `
[go_namespace="go.test",
lucky=true,
planet=EARTH]
module mojom.test;
import "another.file";
import "and.another.file";
const uint16 NUM_MAGI = 3;
struct Foo{
int32 x;
[min_version=2]
string y = "hello";
string? z;
enum Hats {
TOP,
COWBOY = NUM_MAGI,
HARD,
};
};`
test.addTestCase("mojom.test", contents)
// Attributes
test.expectedFile().Attributes = &[]mojom_types.Attribute{
{"go_namespace", &mojom_types.LiteralValueStringValue{"go.test"}},
{"lucky", &mojom_types.LiteralValueBoolValue{true}},
{"planet", &mojom_types.LiteralValueStringValue{"EARTH"}},
}
// Imports
test.expectedFile().Imports = &[]string{
"another.file.canonical", "and.another.file.canonical",
}
// DeclaredMojomObjects
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:mojom.test.Foo"}
test.expectedFile().DeclaredMojomObjects.TopLevelConstants = &[]string{"TYPE_KEY:mojom.test.NUM_MAGI"}
// Resolved Constants
// NUM_MAGI
test.expectedGraph().ResolvedConstants["TYPE_KEY:mojom.test.NUM_MAGI"] = mojom_types.DeclaredConstant{
DeclData: *test.newDeclData("NUM_MAGI", "mojom.test.NUM_MAGI"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Uint16},
Value: &mojom_types.ValueLiteralValue{&mojom_types.LiteralValueInt8Value{3}},
}
// ResolvedTypes
// struct Foo
test.expectedGraph().ResolvedTypes["TYPE_KEY:mojom.test.Foo"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: &mojom_types.DeclarationData{
ShortName: stringPointer("Foo"),
FullIdentifier: stringPointer("mojom.test.Foo"),
DeclaredOrdinal: -1,
DeclarationOrder: -1,
SourceFileInfo: &mojom_types.SourceFileInfo{
FileName: test.fileName(),
},
ContainedDeclarations: &mojom_types.ContainedDeclarations{
Enums: &[]string{"TYPE_KEY:mojom.test.Foo.Hats"}},
},
Fields: []mojom_types.StructField{
// field x
{
DeclData: test.newShortDeclDataO(0, -1, "x"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
},
// field y
{
DeclData: test.newShortDeclDataAO(1, -1, "y", &[]mojom_types.Attribute{{"min_version", &mojom_types.LiteralValueInt8Value{2}}}),
Type: &mojom_types.TypeStringType{mojom_types.StringType{false}},
DefaultValue: &mojom_types.DefaultFieldValueValue{&mojom_types.ValueLiteralValue{&mojom_types.LiteralValueStringValue{"hello"}}},
},
// field z
{
DeclData: test.newShortDeclDataO(2, -1, "z"),
Type: &mojom_types.TypeStringType{mojom_types.StringType{true}},
},
},
}}
// enum Hats
test.expectedGraph().ResolvedTypes["TYPE_KEY:mojom.test.Foo.Hats"] = &mojom_types.UserDefinedTypeEnumType{mojom_types.MojomEnum{
DeclData: test.newContainedDeclData("Hats", "mojom.test.Foo.Hats", stringPointer("TYPE_KEY:mojom.test.Foo")),
Values: []mojom_types.EnumValue{
// value TOP
mojom_types.EnumValue{
DeclData: test.newDeclData("TOP", "mojom.test.Foo.Hats.TOP"),
IntValue: 0,
},
// value COWBOY
mojom_types.EnumValue{
DeclData: test.newDeclData("COWBOY", "mojom.test.Foo.Hats.COWBOY"),
IntValue: 3,
InitializerValue: &mojom_types.ValueConstantReference{mojom_types.ConstantReference{
Identifier: "NUM_MAGI",
ConstantKey: "TYPE_KEY:mojom.test.NUM_MAGI",
}},
},
// value HARD
mojom_types.EnumValue{
DeclData: test.newDeclData("HARD", "mojom.test.Foo.Hats.HARD"),
IntValue: 4,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Execute all of the test cases.
////////////////////////////////////////////////////////////
for _, c := range test.cases {
// Parse and resolve the mojom input.
descriptor := mojom.NewMojomDescriptor()
parser := parser.MakeParser(c.fileName, c.fileName, c.mojomContents, descriptor, nil)
parser.Parse()
if !parser.OK() {
t.Errorf("Parsing error for %s: %s", c.fileName, parser.GetError().Error())
continue
}
if err := descriptor.Resolve(); err != nil {
t.Errorf("Resolve error for %s: %s", c.fileName, err.Error())
continue
}
if err := descriptor.ComputeFinalData(); err != nil {
t.Errorf("ComputeFinalData error for %s: %s", c.fileName, err.Error())
continue
}
if err := descriptor.DetectIllFoundedTypes(); err != nil {
t.Errorf("DetectIllFoundedTypes error for %s: %s", c.fileName, err.Error())
continue
}
// Simulate setting the canonical file name for the imported files. In real operation
// this step is done in parser_driver.go when each of the imported files are parsed.
mojomFile := parser.GetMojomFile()
if mojomFile.Imports != nil {
for _, imp := range mojomFile.Imports {
imp.CanonicalFileName = fmt.Sprintf("%s.canonical", imp.SpecifiedName)
}
}
// Serialize
bytes, _, err := serialize(descriptor, false, false, c.lineAndcolumnNumbers, false)
if err != nil {
t.Errorf("Serialization error for %s: %s", c.fileName, err.Error())
continue
}
// Serialize again and check for consistency.
bytes2, _, err := serialize(descriptor, false, false, c.lineAndcolumnNumbers, false)
if err != nil {
t.Errorf("Serialization error for %s: %s", c.fileName, err.Error())
continue
}
if !reflect.DeepEqual(bytes, bytes2) {
t.Errorf("Inconsistent serialization for %s:\nbytes=%v\nbytes2=%v\n",
c.fileName, bytes, bytes2)
continue
}
// Deserialize
decoder := bindings.NewDecoder(bytes, nil)
fileGraph := mojom_files.MojomFileGraph{}
fileGraph.Decode(decoder)
// Compare
if err := compareTwoGoObjects(c.expectedGraph, &fileGraph); err != nil {
t.Errorf("%s:\n%s", c.fileName, err.Error())
continue
}
}
}
// TestWithComputedData is similar to the previous test except that it sets
// emitComputedPackingData = true.
func TestWithComputedData(t *testing.T) {
test := singleFileTest{}
////////////////////////////////////////////////////////////
// Test Case: Empty struct
////////////////////////////////////////////////////////////
{
contents := `
struct Foo{
};`
test.addTestCase("", contents)
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:Foo"}
test.expectedGraph().ResolvedTypes["TYPE_KEY:Foo"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: test.newDeclData("Foo", "Foo"),
Fields: []mojom_types.StructField{},
VersionInfo: &[]mojom_types.StructVersion{
mojom_types.StructVersion{
VersionNumber: 0,
NumFields: 0,
NumBytes: 8,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: Test struct field min versions: 1,2
////////////////////////////////////////////////////////////
{
contents := `
struct Foo{
int32 x;
int32 y;
[MinVersion = 1]
array<int32>? z;
[MinVersion = 2]
array<int32>? w;
};`
test.addTestCase("", contents)
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:Foo"}
test.expectedGraph().ResolvedTypes["TYPE_KEY:Foo"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: test.newDeclData("Foo", "Foo"),
Fields: []mojom_types.StructField{
// The fields are in ordinal order and the first two arguments to newShortDeclDataO() are
// declarationOrder and declaredOrdinal.
// field x
{
DeclData: test.newShortDeclDataO(0, -1, "x"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Offset: 0,
},
// field y
{
DeclData: test.newShortDeclDataO(1, -1, "y"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Offset: 4,
},
// field z
{
DeclData: test.newShortDeclDataAO(2, -1, "z", &[]mojom_types.Attribute{{"MinVersion", &mojom_types.LiteralValueInt8Value{1}}}),
Type: &mojom_types.TypeArrayType{mojom_types.ArrayType{true, -1, &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32}}},
MinVersion: 1,
Offset: 8,
},
// field w
{
DeclData: test.newShortDeclDataAO(3, -1, "w", &[]mojom_types.Attribute{{"MinVersion", &mojom_types.LiteralValueInt8Value{2}}}),
Type: &mojom_types.TypeArrayType{mojom_types.ArrayType{true, -1, &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32}}},
MinVersion: 2,
Offset: 16,
},
},
VersionInfo: &[]mojom_types.StructVersion{
mojom_types.StructVersion{
VersionNumber: 0,
NumFields: 2,
NumBytes: 16,
},
mojom_types.StructVersion{
VersionNumber: 1,
NumFields: 3,
NumBytes: 24,
},
mojom_types.StructVersion{
VersionNumber: 2,
NumFields: 4,
NumBytes: 32,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: Test struct field min versions: 1, 3
////////////////////////////////////////////////////////////
{
contents := `
struct Foo{
int32 x;
int32 y;
[MinVersion = 1]
array<int32>? z;
[MinVersion = 3]
array<int32>? w;
};`
test.addTestCase("", contents)
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:Foo"}
test.expectedGraph().ResolvedTypes["TYPE_KEY:Foo"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: test.newDeclData("Foo", "Foo"),
Fields: []mojom_types.StructField{
// The fields are in ordinal order and the first two arguments to newShortDeclDataO() are
// declarationOrder and declaredOrdinal.
// field x
{
DeclData: test.newShortDeclDataO(0, -1, "x"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Offset: 0,
},
// field y
{
DeclData: test.newShortDeclDataO(1, -1, "y"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Offset: 4,
},
// field z
{
DeclData: test.newShortDeclDataAO(2, -1, "z", &[]mojom_types.Attribute{{"MinVersion", &mojom_types.LiteralValueInt8Value{1}}}),
Type: &mojom_types.TypeArrayType{mojom_types.ArrayType{true, -1, &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32}}},
MinVersion: 1,
Offset: 8,
},
// field w
{
DeclData: test.newShortDeclDataAO(3, -1, "w", &[]mojom_types.Attribute{{"MinVersion", &mojom_types.LiteralValueInt8Value{3}}}),
Type: &mojom_types.TypeArrayType{mojom_types.ArrayType{true, -1, &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32}}},
MinVersion: 3,
Offset: 16,
},
},
VersionInfo: &[]mojom_types.StructVersion{
mojom_types.StructVersion{
VersionNumber: 0,
NumFields: 2,
NumBytes: 16,
},
mojom_types.StructVersion{
VersionNumber: 1,
NumFields: 3,
NumBytes: 24,
},
mojom_types.StructVersion{
VersionNumber: 3,
NumFields: 4,
NumBytes: 32,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: Test struct field min versions: 1, 1
////////////////////////////////////////////////////////////
{
contents := `
struct Foo{
int32 x;
int32 y;
[MinVersion = 1]
array<int32>? z;
[MinVersion = 1]
array<int32>? w;
};`
test.addTestCase("", contents)
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:Foo"}
test.expectedGraph().ResolvedTypes["TYPE_KEY:Foo"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: test.newDeclData("Foo", "Foo"),
Fields: []mojom_types.StructField{
// The fields are in ordinal order and the first two arguments to newShortDeclDataO() are
// declarationOrder and declaredOrdinal.
// field x
{
DeclData: test.newShortDeclDataO(0, -1, "x"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Offset: 0,
},
// field y
{
DeclData: test.newShortDeclDataO(1, -1, "y"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Offset: 4,
},
// field z
{
DeclData: test.newShortDeclDataAO(2, -1, "z", &[]mojom_types.Attribute{{"MinVersion", &mojom_types.LiteralValueInt8Value{1}}}),
Type: &mojom_types.TypeArrayType{mojom_types.ArrayType{true, -1, &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32}}},
MinVersion: 1,
Offset: 8,
},
// field w
{
DeclData: test.newShortDeclDataAO(3, -1, "w", &[]mojom_types.Attribute{{"MinVersion", &mojom_types.LiteralValueInt8Value{1}}}),
Type: &mojom_types.TypeArrayType{mojom_types.ArrayType{true, -1, &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32}}},
MinVersion: 1,
Offset: 16,
},
},
VersionInfo: &[]mojom_types.StructVersion{
mojom_types.StructVersion{
VersionNumber: 0,
NumFields: 2,
NumBytes: 16,
},
mojom_types.StructVersion{
VersionNumber: 1,
NumFields: 4,
NumBytes: 32,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: Test struct field min versions: 1,2 with specified ordinals
////////////////////////////////////////////////////////////
{
contents := `
struct Foo{
int32 y@1;
[MinVersion = 1]
array<int32>? z@2;
[MinVersion = 2]
array<int32>? w@3;
int32 x@0;
};`
test.addTestCase("", contents)
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:Foo"}
test.expectedGraph().ResolvedTypes["TYPE_KEY:Foo"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: test.newDeclData("Foo", "Foo"),
Fields: []mojom_types.StructField{
// The fields are in ordinal order and the first two arguments to newShortDeclDataO() are
// declarationOrder and declaredOrdinal.
// field x
{
DeclData: test.newShortDeclDataO(3, 0, "x"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Offset: 0,
},
// field y
{
DeclData: test.newShortDeclDataO(0, 1, "y"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Offset: 4,
},
// field z
{
DeclData: test.newShortDeclDataAO(1, 2, "z", &[]mojom_types.Attribute{{"MinVersion", &mojom_types.LiteralValueInt8Value{1}}}),
Type: &mojom_types.TypeArrayType{mojom_types.ArrayType{true, -1, &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32}}},
MinVersion: 1,
Offset: 8,
},
// field w
{
DeclData: test.newShortDeclDataAO(2, 3, "w", &[]mojom_types.Attribute{{"MinVersion", &mojom_types.LiteralValueInt8Value{2}}}),
Type: &mojom_types.TypeArrayType{mojom_types.ArrayType{true, -1, &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32}}},
MinVersion: 2,
Offset: 16,
},
},
VersionInfo: &[]mojom_types.StructVersion{
mojom_types.StructVersion{
VersionNumber: 0,
NumFields: 2,
NumBytes: 16,
},
mojom_types.StructVersion{
VersionNumber: 1,
NumFields: 3,
NumBytes: 24,
},
mojom_types.StructVersion{
VersionNumber: 2,
NumFields: 4,
NumBytes: 32,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: Method and parameter versions.
////////////////////////////////////////////////////////////
{
contents := `
interface MyInterface42 {
DoIt(int8 x0, [MinVersion=1] int64 x1, [MinVersion=2] int8 x2)
=> (int8 y0, [MinVersion=1] int64 y1);
[MinVersion=1]
DoItAgain(int8 x0);
[MinVersion=2]
AndAgain();
};`
test.addTestCase("", contents)
test.expectedFile().DeclaredMojomObjects.Interfaces = &[]string{"TYPE_KEY:MyInterface42"}
test.expectedGraph().ResolvedTypes["TYPE_KEY:MyInterface42"] = &mojom_types.UserDefinedTypeInterfaceType{mojom_types.MojomInterface{
DeclData: test.newDeclData("MyInterface42", "MyInterface42"),
CurrentVersion: 2,
Methods: map[uint32]mojom_types.MojomMethod{
// DoIt
0: mojom_types.MojomMethod{
DeclData: test.newDeclDataO(0, -1, "DoIt", ""),
Parameters: mojom_types.MojomStruct{
DeclData: test.newDeclData("DoIt-request", ""),
Fields: []mojom_types.StructField{
// The fields are in ordinal order and the first two arguments to newShortDeclDataO() are
// declarationOrder and declaredOrdinal.
// x0
mojom_types.StructField{
DeclData: test.newDeclDataO(0, -1, "x0", ""),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int8},
Offset: 0,
MinVersion: 0,
},
// x1
mojom_types.StructField{
DeclData: test.newShortDeclDataAO(1, -1, "x1", &[]mojom_types.Attribute{{"MinVersion", &mojom_types.LiteralValueInt8Value{1}}}),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int64},
Offset: 8,
MinVersion: 1,
},
// x2
mojom_types.StructField{
DeclData: test.newShortDeclDataAO(2, -1, "x2", &[]mojom_types.Attribute{{"MinVersion", &mojom_types.LiteralValueInt8Value{2}}}),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int8},
Offset: 1,
MinVersion: 2,
},
},
VersionInfo: &[]mojom_types.StructVersion{
mojom_types.StructVersion{
VersionNumber: 0,
NumFields: 1,
NumBytes: 16,
},
mojom_types.StructVersion{
VersionNumber: 1,
NumFields: 2,
NumBytes: 24,
},
mojom_types.StructVersion{
VersionNumber: 2,
NumFields: 3,
NumBytes: 24,
},
},
},
ResponseParams: &mojom_types.MojomStruct{
DeclData: test.newDeclData("DoIt-response", ""),
Fields: []mojom_types.StructField{
// yo
mojom_types.StructField{
DeclData: test.newDeclDataO(0, -1, "y0", ""),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int8},
Offset: 0,
MinVersion: 0,
},
// y1
mojom_types.StructField{
DeclData: test.newShortDeclDataAO(1, -1, "y1", &[]mojom_types.Attribute{{"MinVersion", &mojom_types.LiteralValueInt8Value{1}}}),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int64},
Offset: 8,
MinVersion: 1,
},
},
VersionInfo: &[]mojom_types.StructVersion{
mojom_types.StructVersion{
VersionNumber: 0,
NumFields: 1,
NumBytes: 16,
},
mojom_types.StructVersion{
VersionNumber: 1,
NumFields: 2,
NumBytes: 24,
},
},
},
},
// DoItAgain
1: mojom_types.MojomMethod{
DeclData: test.newShortDeclDataAO(1, -1, "DoItAgain", &[]mojom_types.Attribute{{"MinVersion", &mojom_types.LiteralValueInt8Value{1}}}),
Parameters: mojom_types.MojomStruct{
DeclData: test.newDeclData("DoItAgain-request", ""),
Fields: []mojom_types.StructField{
// The fields are in ordinal order and the first two arguments to newShortDeclDataO() are
// declarationOrder and declaredOrdinal.
// x0
mojom_types.StructField{
DeclData: test.newDeclDataO(0, -1, "x0", ""),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int8},
Offset: 0,
MinVersion: 0,
},
},
VersionInfo: &[]mojom_types.StructVersion{
mojom_types.StructVersion{
VersionNumber: 0,
NumFields: 1,
NumBytes: 16,
},
},
},
Ordinal: 1,
MinVersion: 1,
},
// AndAgain
2: mojom_types.MojomMethod{
DeclData: test.newShortDeclDataAO(2, -1, "AndAgain", &[]mojom_types.Attribute{{"MinVersion", &mojom_types.LiteralValueInt8Value{2}}}),
Parameters: mojom_types.MojomStruct{
DeclData: test.newDeclData("AndAgain-request", ""),
Fields: []mojom_types.StructField{},
VersionInfo: &[]mojom_types.StructVersion{
mojom_types.StructVersion{
VersionNumber: 0,
NumFields: 0,
NumBytes: 8,
},
},
},
Ordinal: 2,
MinVersion: 2,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: 3 boolean fields
////////////////////////////////////////////////////////////
{
contents := `
struct MyStruct1 {
bool b1;
bool b2;
bool b3;
};`
test.addTestCase("", contents)
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:MyStruct1"}
test.expectedGraph().ResolvedTypes["TYPE_KEY:MyStruct1"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: test.newDeclData("MyStruct1", "MyStruct1"),
Fields: []mojom_types.StructField{
// The fields are in ordinal order and the first two arguments to newShortDeclDataO() are
// declarationOrder and declaredOrdinal.
// field b1
{
DeclData: test.newShortDeclDataO(0, -1, "b1"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 0,
Bit: 0,
},
// field b2
{
DeclData: test.newShortDeclDataO(1, -1, "b2"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 0,
Bit: 1,
},
// field b3
{
DeclData: test.newShortDeclDataO(2, -1, "b3"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 0,
Bit: 2,
},
},
VersionInfo: &[]mojom_types.StructVersion{
mojom_types.StructVersion{
VersionNumber: 0,
NumFields: 3,
NumBytes: 16,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: int8 field + 2 boolean fields + int32field + 2 boolean fields
////////////////////////////////////////////////////////////
{
contents := `
struct MyStruct1 {
int8 x;
bool b1;
bool b2;
int32 y;
bool b3;
bool b4;
};`
test.addTestCase("", contents)
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:MyStruct1"}
test.expectedGraph().ResolvedTypes["TYPE_KEY:MyStruct1"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: test.newDeclData("MyStruct1", "MyStruct1"),
Fields: []mojom_types.StructField{
// The fields are in ordinal order and the first two arguments to newShortDeclDataO() are
// declarationOrder and declaredOrdinal.
// field x
{
DeclData: test.newShortDeclDataO(0, -1, "x"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int8},
Offset: 0,
},
// field b1
{
DeclData: test.newShortDeclDataO(1, -1, "b1"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 1,
Bit: 0,
},
// field b2
{
DeclData: test.newShortDeclDataO(2, -1, "b2"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 1,
Bit: 1,
},
// field y
{
DeclData: test.newShortDeclDataO(3, -1, "y"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Offset: 4,
},
// field b3
{
DeclData: test.newShortDeclDataO(4, -1, "b3"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 1,
Bit: 2,
},
// field b4
{
DeclData: test.newShortDeclDataO(5, -1, "b4"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 1,
Bit: 3,
},
},
VersionInfo: &[]mojom_types.StructVersion{
mojom_types.StructVersion{
VersionNumber: 0,
NumFields: 6,
NumBytes: 16,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: int8 + int64 + bool + int32 + int8 + bool + int16
////////////////////////////////////////////////////////////
{
contents := `
struct MyStruct1 {
int8 x;
int64 y;
bool b1;
int32 z;
int8 w;
bool b2;
int16 r;
};`
test.addTestCase("", contents)
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:MyStruct1"}
test.expectedGraph().ResolvedTypes["TYPE_KEY:MyStruct1"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: test.newDeclData("MyStruct1", "MyStruct1"),
Fields: []mojom_types.StructField{
// The fields are in ordinal order and the first two arguments to newShortDeclDataO() are
// declarationOrder and declaredOrdinal.
// field x
{
DeclData: test.newShortDeclDataO(0, -1, "x"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int8},
Offset: 0,
},
// field y
{
DeclData: test.newShortDeclDataO(1, -1, "y"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int64},
Offset: 8,
},
// field b1
{
DeclData: test.newShortDeclDataO(2, -1, "b1"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 1,
Bit: 0,
},
// field z
{
DeclData: test.newShortDeclDataO(3, -1, "z"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Offset: 4,
},
// field w
{
DeclData: test.newShortDeclDataO(4, -1, "w"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int8},
Offset: 2,
},
// field b2
{
DeclData: test.newShortDeclDataO(5, -1, "b2"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 1,
Bit: 1,
},
// field r
{
DeclData: test.newShortDeclDataO(6, -1, "r"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int16},
Offset: 16,
},
},
VersionInfo: &[]mojom_types.StructVersion{
mojom_types.StructVersion{
VersionNumber: 0,
NumFields: 7,
NumBytes: 32,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: Specified ordinals with int8 + int64 + bool + int32 + int8 + bool + int16
////////////////////////////////////////////////////////////
{
contents := `
struct MyStruct1 {
int64 y@1;
bool b1@2;
int32 z@3;
bool b2@5;
int16 r@6;
int8 x@0;
int8 w@4;
};`
test.addTestCase("", contents)
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:MyStruct1"}
test.expectedGraph().ResolvedTypes["TYPE_KEY:MyStruct1"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: test.newDeclData("MyStruct1", "MyStruct1"),
Fields: []mojom_types.StructField{
// The fields are in ordinal order and the first two arguments to newShortDeclDataO() are
// declarationOrder and declaredOrdinal.
// field x
{
DeclData: test.newShortDeclDataO(5, 0, "x"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int8},
Offset: 0,
},
// field y
{
DeclData: test.newShortDeclDataO(0, 1, "y"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int64},
Offset: 8,
},
// field b1
{
DeclData: test.newShortDeclDataO(1, 2, "b1"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 1,
Bit: 0,
},
// field z
{
DeclData: test.newShortDeclDataO(2, 3, "z"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Offset: 4,
},
// field w
{
DeclData: test.newShortDeclDataO(6, 4, "w"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int8},
Offset: 2,
},
// field b2
{
DeclData: test.newShortDeclDataO(3, 5, "b2"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 1,
Bit: 1,
},
// field r
{
DeclData: test.newShortDeclDataO(4, 6, "r"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int16},
Offset: 16,
},
},
VersionInfo: &[]mojom_types.StructVersion{
mojom_types.StructVersion{
VersionNumber: 0,
NumFields: 7,
NumBytes: 32,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: Ten bools
////////////////////////////////////////////////////////////
{
contents := `
struct MyStruct1 {
bool b0;
bool b1;
bool b2;
bool b3;
bool b4;
bool b5;
bool b6;
bool b7;
bool b8;
bool b9;
};`
test.addTestCase("", contents)
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:MyStruct1"}
test.expectedGraph().ResolvedTypes["TYPE_KEY:MyStruct1"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: test.newDeclData("MyStruct1", "MyStruct1"),
Fields: []mojom_types.StructField{
// The fields are in ordinal order and the first two arguments to newShortDeclDataO() are
// declarationOrder and declaredOrdinal.
{
DeclData: test.newShortDeclDataO(0, -1, "b0"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 0,
Bit: 0,
},
{
DeclData: test.newShortDeclDataO(1, -1, "b1"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 0,
Bit: 1,
},
{
DeclData: test.newShortDeclDataO(2, -1, "b2"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 0,
Bit: 2,
},
{
DeclData: test.newShortDeclDataO(3, -1, "b3"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 0,
Bit: 3,
},
{
DeclData: test.newShortDeclDataO(4, -1, "b4"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 0,
Bit: 4,
},
{
DeclData: test.newShortDeclDataO(5, -1, "b5"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 0,
Bit: 5,
},
{
DeclData: test.newShortDeclDataO(6, -1, "b6"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 0,
Bit: 6,
},
{
DeclData: test.newShortDeclDataO(7, -1, "b7"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 0,
Bit: 7,
},
{
DeclData: test.newShortDeclDataO(8, -1, "b8"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 1,
Bit: 0,
},
{
DeclData: test.newShortDeclDataO(9, -1, "b9"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
Offset: 1,
Bit: 1,
},
},
VersionInfo: &[]mojom_types.StructVersion{
mojom_types.StructVersion{
VersionNumber: 0,
NumFields: 10,
NumBytes: 16,
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: int8 + union + struct + interface-request + int32 + interface
//
// x intfcreqst my_union----------------------------------------> my_struct------------> y--------> my_interface--------->
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
//
////////////////////////////////////////////////////////////
{
contents := `
union MyUnion1{};
interface MyInterface1{};
struct MyStruct1 {
int8 x;
MyUnion1 my_union;
MyStruct1? my_struct;
MyInterface1& my_interface_request;
int32 y;
MyInterface1 my_interface;
};`
test.addTestCase("", contents)
test.expectedFile().DeclaredMojomObjects.Unions = &[]string{"TYPE_KEY:MyUnion1"}
test.expectedFile().DeclaredMojomObjects.Interfaces = &[]string{"TYPE_KEY:MyInterface1"}
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:MyStruct1"}
// MyStruct1
test.expectedGraph().ResolvedTypes["TYPE_KEY:MyStruct1"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: test.newDeclData("MyStruct1", "MyStruct1"),
Fields: []mojom_types.StructField{
// The fields are in ordinal order and the first two arguments to newShortDeclDataO() are
// declarationOrder and declaredOrdinal.
// field x
{
DeclData: test.newShortDeclDataO(0, -1, "x"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int8},
Offset: 0,
},
// field my_union
{
DeclData: test.newShortDeclDataO(1, -1, "my_union"),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("MyUnion1"), stringPointer("TYPE_KEY:MyUnion1")}},
Offset: 8,
},
// field my_struct
{
DeclData: test.newShortDeclDataO(2, -1, "my_struct"),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
true, false, stringPointer("MyStruct1"), stringPointer("TYPE_KEY:MyStruct1")}},
Offset: 24,
},
// field my_interface_request
{
DeclData: test.newShortDeclDataO(3, -1, "my_interface_request"),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, true, stringPointer("MyInterface1"), stringPointer("TYPE_KEY:MyInterface1")}},
Offset: 4,
},
// field y
{
DeclData: test.newShortDeclDataO(4, -1, "y"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Offset: 32,
},
// field my_interface
{
DeclData: test.newShortDeclDataO(5, -1, "my_interface"),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("MyInterface1"), stringPointer("TYPE_KEY:MyInterface1")}},
Offset: 36,
},
},
VersionInfo: &[]mojom_types.StructVersion{
mojom_types.StructVersion{
VersionNumber: 0,
NumFields: 6,
NumBytes: 56,
},
},
}}
// MyUnion1
test.expectedGraph().ResolvedTypes["TYPE_KEY:MyUnion1"] = &mojom_types.UserDefinedTypeUnionType{mojom_types.MojomUnion{
DeclData: test.newDeclData("MyUnion1", "MyUnion1"),
Fields: []mojom_types.UnionField{},
}}
// MyInterface1
test.expectedGraph().ResolvedTypes["TYPE_KEY:MyInterface1"] = &mojom_types.UserDefinedTypeInterfaceType{mojom_types.MojomInterface{
DeclData: test.newDeclData("MyInterface1", "MyInterface1"),
Methods: map[uint32]mojom_types.MojomMethod{},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Test Case: Multiple versions with int8 + union + struct + interface-request + handle + interface
//
// x intfcreqst my_union----------------------------------------> my_struct------------> y--------> my_interface--------->
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
//
////////////////////////////////////////////////////////////
{
contents := `
union MyUnion1{};
interface MyInterface1{};
struct MyStruct1 {
int8 x;
MyUnion1 my_union;
MyStruct1? my_struct;
[MinVersion=1]
MyInterface1&? my_interface_request;
[MinVersion=2]
int32 y;
[MinVersion=2]
MyInterface1? my_interface;
};`
test.addTestCase("", contents)
test.expectedFile().DeclaredMojomObjects.Unions = &[]string{"TYPE_KEY:MyUnion1"}
test.expectedFile().DeclaredMojomObjects.Interfaces = &[]string{"TYPE_KEY:MyInterface1"}
test.expectedFile().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:MyStruct1"}
// MyStruct1
test.expectedGraph().ResolvedTypes["TYPE_KEY:MyStruct1"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: test.newDeclData("MyStruct1", "MyStruct1"),
Fields: []mojom_types.StructField{
// The fields are in ordinal order and the first two arguments to newShortDeclDataO() are
// declarationOrder and declaredOrdinal.
// field x
{
DeclData: test.newShortDeclDataO(0, -1, "x"),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int8},
Offset: 0,
},
// field my_union
{
DeclData: test.newShortDeclDataO(1, -1, "my_union"),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("MyUnion1"), stringPointer("TYPE_KEY:MyUnion1")}},
Offset: 8,
},
// field my_struct
{
DeclData: test.newShortDeclDataO(2, -1, "my_struct"),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
true, false, stringPointer("MyStruct1"), stringPointer("TYPE_KEY:MyStruct1")}},
Offset: 24,
},
// field my_interface_request
{
DeclData: test.newShortDeclDataAO(3, -1, "my_interface_request", &[]mojom_types.Attribute{{"MinVersion", &mojom_types.LiteralValueInt8Value{1}}}),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
true, true, stringPointer("MyInterface1"), stringPointer("TYPE_KEY:MyInterface1")}},
Offset: 4,
MinVersion: 1,
},
// field y
{
DeclData: test.newShortDeclDataAO(4, -1, "y", &[]mojom_types.Attribute{{"MinVersion", &mojom_types.LiteralValueInt8Value{2}}}),
Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
Offset: 32,
MinVersion: 2,
},
// field my_interface
{
DeclData: test.newShortDeclDataAO(5, -1, "my_interface", &[]mojom_types.Attribute{{"MinVersion", &mojom_types.LiteralValueInt8Value{2}}}),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
true, false, stringPointer("MyInterface1"), stringPointer("TYPE_KEY:MyInterface1")}},
Offset: 36,
MinVersion: 2,
},
},
VersionInfo: &[]mojom_types.StructVersion{
mojom_types.StructVersion{
VersionNumber: 0,
NumFields: 3,
NumBytes: 40,
},
mojom_types.StructVersion{
VersionNumber: 1,
NumFields: 4,
NumBytes: 40,
},
mojom_types.StructVersion{
VersionNumber: 2,
NumFields: 6,
NumBytes: 56,
},
},
}}
// MyUnion1
test.expectedGraph().ResolvedTypes["TYPE_KEY:MyUnion1"] = &mojom_types.UserDefinedTypeUnionType{mojom_types.MojomUnion{
DeclData: test.newDeclData("MyUnion1", "MyUnion1"),
Fields: []mojom_types.UnionField{},
}}
// MyInterface1
test.expectedGraph().ResolvedTypes["TYPE_KEY:MyInterface1"] = &mojom_types.UserDefinedTypeInterfaceType{mojom_types.MojomInterface{
DeclData: test.newDeclData("MyInterface1", "MyInterface1"),
Methods: map[uint32]mojom_types.MojomMethod{},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Execute all of the test cases.
////////////////////////////////////////////////////////////
for _, c := range test.cases {
// Parse and resolve the mojom input.
descriptor := mojom.NewMojomDescriptor()
parser := parser.MakeParser(c.fileName, c.fileName, c.mojomContents, descriptor, nil)
parser.Parse()
if !parser.OK() {
t.Errorf("Parsing error for %s: %s", c.fileName, parser.GetError().Error())
continue
}
if err := descriptor.Resolve(); err != nil {
t.Errorf("Resolve error for %s: %s", c.fileName, err.Error())
continue
}
if err := descriptor.ComputeFinalData(); err != nil {
t.Errorf("ComputeFinalData error for %s: %s", c.fileName, err.Error())
continue
}
if err := descriptor.DetectIllFoundedTypes(); err != nil {
t.Errorf("DetectIllFoundedTypes error for %s: %s", c.fileName, err.Error())
continue
}
// Simulate setting the canonical file name for the imported files. In real operation
// this step is done in parser_driver.go when each of the imported files are parsed.
mojomFile := parser.GetMojomFile()
if mojomFile.Imports != nil {
for _, imp := range mojomFile.Imports {
imp.CanonicalFileName = fmt.Sprintf("%s.canonical", imp.SpecifiedName)
}
}
// Serialize. Notice that the fourth argument is |true|.
bytes, _, err := serialize(descriptor, false, false, true, false)
if err != nil {
t.Errorf("Serialization error for %s: %s", c.fileName, err.Error())
continue
}
// Serialize again and check for consistency.
bytes2, _, err := serialize(descriptor, false, false, true, false)
if err != nil {
t.Errorf("Serialization error for %s: %s", c.fileName, err.Error())
continue
}
if !reflect.DeepEqual(bytes, bytes2) {
t.Errorf("Inconsistent serialization for %s:\nbytes=%v\nbytes2=%v\n",
c.fileName, bytes, bytes2)
continue
}
// Deserialize
decoder := bindings.NewDecoder(bytes, nil)
fileGraph := mojom_files.MojomFileGraph{}
fileGraph.Decode(decoder)
// Compare
if err := compareTwoGoObjects(c.expectedGraph, &fileGraph); err != nil {
t.Errorf("%s:\n%s", c.fileName, err.Error())
continue
}
}
}
// TestMetaDataOnlyMode tests parsing and serialization in meta-data-only
// mode. Only file-level attributes and the 'module' statement should be
// parsed.
func TestMetaDataOnlyMode(t *testing.T) {
test := singleFileTest{}
////////////////////////////////////////////////////////////
// Test Case:
////////////////////////////////////////////////////////////
{
contents := `
[go_namespace="go.test",
lucky=true,
planet=EARTH]
module mojom.test;
import "another.file";
import "and.another.file";
const uint16 NUM_MAGI = 3;
struct Foo{
int32 x;
[min_version=2]
string y = "hello";
string? z;
enum Hats {
TOP,
COWBOY = NUM_MAGI,
HARD,
};
};`
test.addTestCase("mojom.test", contents)
// Attributes
test.expectedFile().Attributes = &[]mojom_types.Attribute{
{"go_namespace", &mojom_types.LiteralValueStringValue{"go.test"}},
{"lucky", &mojom_types.LiteralValueBoolValue{true}},
{"planet", &mojom_types.LiteralValueStringValue{"EARTH"}},
}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Execute all of the test cases.
////////////////////////////////////////////////////////////
for _, c := range test.cases {
// Parse and resolve the mojom input.
descriptor := mojom.NewMojomDescriptor()
parser := parser.MakeParser(c.fileName, c.fileName, c.mojomContents, descriptor, nil)
parser.SetMetaDataOnlyMode(true)
parser.Parse()
if !parser.OK() {
t.Errorf("Parsing error for %s: %s", c.fileName, parser.GetError().Error())
continue
}
if err := descriptor.Resolve(); err != nil {
t.Errorf("Resolve error for %s: %s", c.fileName, err.Error())
continue
}
if err := descriptor.ComputeFinalData(); err != nil {
t.Errorf("ComputeFinalData error for %s: %s", c.fileName, err.Error())
continue
}
if err := descriptor.DetectIllFoundedTypes(); err != nil {
t.Errorf("DetectIllFoundedTypes error for %s: %s", c.fileName, err.Error())
continue
}
// Serialize
bytes, _, err := serialize(descriptor, false, false, c.lineAndcolumnNumbers, false)
if err != nil {
t.Errorf("Serialization error for %s: %s", c.fileName, err.Error())
continue
}
// Deserialize
decoder := bindings.NewDecoder(bytes, nil)
fileGraph := mojom_files.MojomFileGraph{}
fileGraph.Decode(decoder)
// Compare
if err := compareTwoGoObjects(c.expectedGraph, &fileGraph); err != nil {
t.Errorf("%s:\n%s", c.fileName, err.Error())
continue
}
}
}
////////////////////////////////////////////
/// Two-File Tests
///////////////////////////////////////////
// twoFileTestCase stores the data for one serialization test case
// in which two files are added to the file graph.
type twoFileTestCase struct {
// Is file B a top-level file?
topLevel bool
// If file A imports file B then this is the expected string that should
// have been parsed from the import statement. Otherwise this is empty.
importingName string
// The contents of the two files
mojomContentsA string
mojomContentsB string
lineAndcolumnNumbers bool
expectedFileA, expectedFileB *mojom_files.MojomFile
expectedGraph *mojom_files.MojomFileGraph
}
// twoFileTest contains a series of twoFileTestCases and a current
// testCaseNum.
type twoFileTest struct {
cases []twoFileTestCase
testCaseNum int
}
// expectedFileA() returns the expectedFileA of the current test case.
func (t *twoFileTest) expectedFileA() *mojom_files.MojomFile {
return t.cases[t.testCaseNum].expectedFileA
}
// expectedFileB() returns the expectedFileB of the current test case.
func (t *twoFileTest) expectedFileB() *mojom_files.MojomFile {
return t.cases[t.testCaseNum].expectedFileB
}
// expectedGraph() returns the expectedGraph of the current test case.
func (t *twoFileTest) expectedGraph() *mojom_files.MojomFileGraph {
return t.cases[t.testCaseNum].expectedGraph
}
func canonicalFileName(name string) string {
return fmt.Sprintf("/my/file/system/%s", name)
}
// addTestCase() should be invoked at the start of a case in
// TestSingleFileSerialization.
// moduleNameSpace: The expected module namespace for the two parsed files.
// contentsA, contentsB: The .mojom file contents of the two files.
// topLevel: Are we simulating File B being a top-level file (as opposed to
// one found only because it is imported from file A.)
// importingName: If non-empty, the string expected to be parsed from the
// import statement in File A.
func (test *twoFileTest) addTestCase(moduleNameSpace, contentsA, contentsB string,
topLevel bool, importingName string) {
fileNameA := fmt.Sprintf("file%dA", test.testCaseNum)
fileNameB := fmt.Sprintf("file%dB", test.testCaseNum)
test.cases = append(test.cases, twoFileTestCase{topLevel, importingName, contentsA, contentsB, false,
new(mojom_files.MojomFile), new(mojom_files.MojomFile), new(mojom_files.MojomFileGraph)})
test.expectedFileA().FileName = canonicalFileName(fileNameA)
test.expectedFileB().FileName = canonicalFileName(fileNameB)
test.expectedFileA().SpecifiedFileName = stringPointer(fileNameA)
specifiedNameB := ""
if topLevel {
// File B should have a non-empty |specified_file_name| just in case it is a top-level file.
specifiedNameB = fileNameB
}
test.expectedFileB().SpecifiedFileName = stringPointer(specifiedNameB)
test.expectedFileA().ModuleNamespace = &moduleNameSpace
test.expectedFileB().ModuleNamespace = &moduleNameSpace
if importingName != "" {
// Add and import to expected File A.
test.expectedFileA().Imports = new([]string)
*test.expectedFileA().Imports = append(*test.expectedFileA().Imports, test.expectedFileB().FileName)
}
test.expectedGraph().ResolvedTypes = make(map[string]mojom_types.UserDefinedType)
test.expectedGraph().ResolvedConstants = make(map[string]mojom_types.DeclaredConstant)
}
// endTestCase() should be invoked at the end of a case in
// TestSingleFileSerialization.
func (test *twoFileTest) endTestCase() {
test.expectedGraph().Files = make(map[string]mojom_files.MojomFile)
test.expectedGraph().Files[test.expectedFileA().FileName] = *test.expectedFileA()
test.expectedGraph().Files[test.expectedFileB().FileName] = *test.expectedFileB()
test.testCaseNum += 1
}
// TestTwoFileSerialization uses a series of test cases in which the text of two .mojom
// files is specified and the expected MojomFileGraph is specified using Go struct literals.
func TestTwoFileSerialization(t *testing.T) {
test := twoFileTest{}
/////////////////////////////////////////////////////////////
// Test Case: Two top-level files with no import relationship
/////////////////////////////////////////////////////////////
{
contentsA := `
module a.b.c;
struct FooA{
};`
contentsB := `
module a.b.c;
struct FooB{
};`
importingName := "" // File A is not importing file B.
topLevel := true // Simulate that File B is a top-level file.
test.addTestCase("a.b.c", contentsA, contentsB, topLevel, importingName)
// DeclaredMojomObjects
test.expectedFileA().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:a.b.c.FooA"}
test.expectedFileB().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:a.b.c.FooB"}
// struct FooA
test.expectedGraph().ResolvedTypes["TYPE_KEY:a.b.c.FooA"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: newDeclData(test.expectedFileA().FileName, "FooA", "a.b.c.FooA"),
Fields: []mojom_types.StructField{}}}
// struct FooB
test.expectedGraph().ResolvedTypes["TYPE_KEY:a.b.c.FooB"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: newDeclData(test.expectedFileB().FileName, "FooB", "a.b.c.FooB"),
Fields: []mojom_types.StructField{}}}
test.endTestCase()
}
/////////////////////////////////////////////////////////////
// Test Case: Two top-level files where the first imports the second.
/////////////////////////////////////////////////////////////
{
contentsA := `
module a.b.c;
import "myLittleFriend";
struct FooA{
};`
contentsB := `
module a.b.c;
struct FooB{
};`
importingName := "myLittleFriend" // File A is importing File B using this name.
topLevel := true // Simulate the File B is a top-level file.
test.addTestCase("a.b.c", contentsA, contentsB, topLevel, importingName)
// DeclaredMojomObjects
test.expectedFileA().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:a.b.c.FooA"}
test.expectedFileB().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:a.b.c.FooB"}
// struct FooA
test.expectedGraph().ResolvedTypes["TYPE_KEY:a.b.c.FooA"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: newDeclData(test.expectedFileA().FileName, "FooA", "a.b.c.FooA"),
Fields: []mojom_types.StructField{}}}
// struct FooB
test.expectedGraph().ResolvedTypes["TYPE_KEY:a.b.c.FooB"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: newDeclData(test.expectedFileB().FileName, "FooB", "a.b.c.FooB"),
Fields: []mojom_types.StructField{}}}
test.endTestCase()
}
/////////////////////////////////////////////////////////////
// Test Case: A top-level file that imports a non-top-level file.
/////////////////////////////////////////////////////////////
{
contentsA := `
module a.b.c;
import "myLittleFriend";
struct FooA{
};`
contentsB := `
module a.b.c;
struct FooB{
};`
importingName := "myLittleFriend" // File A is importing File B using this name.
topLevel := false // Simulate the File B is not a top-level file.
test.addTestCase("a.b.c", contentsA, contentsB, topLevel, importingName)
// DeclaredMojomObjects
test.expectedFileA().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:a.b.c.FooA"}
test.expectedFileB().DeclaredMojomObjects.Structs = &[]string{"TYPE_KEY:a.b.c.FooB"}
// struct FooA
test.expectedGraph().ResolvedTypes["TYPE_KEY:a.b.c.FooA"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: newDeclData(test.expectedFileA().FileName, "FooA", "a.b.c.FooA"),
Fields: []mojom_types.StructField{}}}
// struct FooB
test.expectedGraph().ResolvedTypes["TYPE_KEY:a.b.c.FooB"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: newDeclData(test.expectedFileB().FileName, "FooB", "a.b.c.FooB"),
Fields: []mojom_types.StructField{}}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Execute all of the test cases.
////////////////////////////////////////////////////////////
for i, c := range test.cases {
descriptor := mojom.NewMojomDescriptor()
// Parse file A.
parserA := parser.MakeParser(c.expectedFileA.FileName, *c.expectedFileA.SpecifiedFileName, c.mojomContentsA, descriptor, nil)
parserA.Parse()
if !parserA.OK() {
t.Errorf("Parsing error for %s: %s", c.expectedFileA.FileName, parserA.GetError().Error())
continue
}
mojomFileA := parserA.GetMojomFile()
// Parse file B.
var importedFrom *mojom.MojomFile
if !c.topLevel {
// If file B is not a top-level file then when the parser for it is constructed we give it a non-nil |importedFrom|.
importedFrom = mojomFileA
}
parserB := parser.MakeParser(c.expectedFileB.FileName, *c.expectedFileB.SpecifiedFileName, c.mojomContentsB, descriptor, importedFrom)
parserB.Parse()
if !parserB.OK() {
t.Errorf("Parsing error for %s: %s", c.expectedFileB.FileName, parserB.GetError().Error())
continue
}
mojomFileB := parserB.GetMojomFile()
// Set the canonical file name for the imported files. In real operation
// this step is done in parser_driver.go when each of the imported files are parsed.
if c.importingName != "" {
// The call to SetCanonicalImportName does a lookup in a map for a key corresponding to the
// first argument. Thus here we are also testing that |importingName| is in fact string
// that was parsed from the .mojom file.
mojomFileA.SetCanonicalImportName(c.importingName, mojomFileB.CanonicalFileName)
}
// Resolve
if err := descriptor.Resolve(); err != nil {
t.Errorf("Resolve error for case %d: %s", i, err.Error())
continue
}
if err := descriptor.ComputeFinalData(); err != nil {
t.Errorf("ComputeFinalData error for case %d: %s", i, err.Error())
continue
}
if err := descriptor.DetectIllFoundedTypes(); err != nil {
t.Errorf("DetectIllFoundedTypes error for case %d: %s", i, err.Error())
continue
}
// Serialize
bytes, _, err := serialize(descriptor, false, false, c.lineAndcolumnNumbers, false)
if err != nil {
t.Errorf("Serialization error for case %d: %s", i, err.Error())
continue
}
// Deserialize
decoder := bindings.NewDecoder(bytes, nil)
fileGraph := mojom_files.MojomFileGraph{}
fileGraph.Decode(decoder)
// Compare
if err := compareTwoGoObjects(c.expectedGraph, &fileGraph); err != nil {
t.Errorf("case %d:\n%s", i, err.Error())
continue
}
}
}
////////////////////////////////////////////
/// Serialized Runtime Type Info Tests
///////////////////////////////////////////
type runtimeTypeInfoTestCase struct {
// The contents of the two files
mojomContentsA string
mojomContentsB string
expectedRuntimeTypeInfoA *mojom_types.RuntimeTypeInfo
expectedRuntimeTypeInfoB *mojom_types.RuntimeTypeInfo
}
type runtimeTypeInfoTest struct {
cases []runtimeTypeInfoTestCase
testCaseNum int
}
func (t *runtimeTypeInfoTest) expectedRuntimeTypeInfoA() *mojom_types.RuntimeTypeInfo {
return t.cases[t.testCaseNum].expectedRuntimeTypeInfoA
}
func (t *runtimeTypeInfoTest) expectedRuntimeTypeInfoB() *mojom_types.RuntimeTypeInfo {
return t.cases[t.testCaseNum].expectedRuntimeTypeInfoB
}
func (test *runtimeTypeInfoTest) addTestCase(contentsA, contentsB string) {
test.cases = append(test.cases, runtimeTypeInfoTestCase{contentsA, contentsB, new(mojom_types.RuntimeTypeInfo), new(mojom_types.RuntimeTypeInfo)})
test.expectedRuntimeTypeInfoA().Services = make(map[string]string)
test.expectedRuntimeTypeInfoA().TypeMap = make(map[string]mojom_types.UserDefinedType)
test.expectedRuntimeTypeInfoB().Services = make(map[string]string)
test.expectedRuntimeTypeInfoB().TypeMap = make(map[string]mojom_types.UserDefinedType)
}
func (test *runtimeTypeInfoTest) fileNameA() string {
return fmt.Sprintf("file%dA", test.testCaseNum)
}
func (test *runtimeTypeInfoTest) fileNameB() string {
return fmt.Sprintf("file%dB", test.testCaseNum)
}
func (test *runtimeTypeInfoTest) endTestCase() {
test.testCaseNum += 1
}
// TestRuntimeTypeInfo uses a series of test cases in which the text of two .mojom
// files is specified and the expected RuntimeTypeInfos are specified using Go struct literals.
func TestRuntimeTypeInfo(t *testing.T) {
test := runtimeTypeInfoTest{}
/////////////////////////////////////////////////////////////
// Test Case: No nterfaces.
/////////////////////////////////////////////////////////////
{
contentsA := `
module a.b.c;
struct FooA{
};`
contentsB := `
module b.c.d;
struct FooB{
};`
test.addTestCase(contentsA, contentsB)
// TypeMap for file A
test.expectedRuntimeTypeInfoA().TypeMap["TYPE_KEY:a.b.c.FooA"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameA(), "FooA", "a.b.c.FooA"),
Fields: []mojom_types.StructField{}}}
// TypeMap for file B
test.expectedRuntimeTypeInfoB().TypeMap["TYPE_KEY:b.c.d.FooB"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameB(), "FooB", "b.c.d.FooB"),
Fields: []mojom_types.StructField{}}}
test.endTestCase()
}
/////////////////////////////////////////////////////////////
// Test Case: Two interfaces: Not top-level.
/////////////////////////////////////////////////////////////
{
contentsA := `
module a.b.c;
struct FooA{
};
interface InterfaceA {
DoIt(FooA x) => (b.c.d.FooB? y);
};
`
contentsB := `
module b.c.d;
struct FooB{
};
interface InterfaceB {
DoIt(a.b.c.FooA x) => (FooB? y);
};
`
test.addTestCase(contentsA, contentsB)
// TypeMap for file A
// FooA
test.expectedRuntimeTypeInfoA().TypeMap["TYPE_KEY:a.b.c.FooA"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameA(), "FooA", "a.b.c.FooA"),
Fields: []mojom_types.StructField{}}}
// InterfaceA
test.expectedRuntimeTypeInfoA().TypeMap["TYPE_KEY:a.b.c.InterfaceA"] = &mojom_types.UserDefinedTypeInterfaceType{mojom_types.MojomInterface{
DeclData: newDeclData(test.fileNameA(), "InterfaceA", "a.b.c.InterfaceA"),
Methods: map[uint32]mojom_types.MojomMethod{
0: mojom_types.MojomMethod{
DeclData: newDeclDataO(0, -1, test.fileNameA(), "DoIt", ""),
Parameters: mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameA(), "DoIt-request", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: newDeclDataO(0, -1, test.fileNameA(), "x", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("FooA"), stringPointer("TYPE_KEY:a.b.c.FooA")}},
},
},
},
ResponseParams: &mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameA(), "DoIt-response", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: newDeclDataO(0, -1, test.fileNameA(), "y", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
true, false, stringPointer("b.c.d.FooB"), stringPointer("TYPE_KEY:b.c.d.FooB")}},
},
},
},
},
},
}}
////////////////////////////////////////////////////////////////////////
// TypeMap for file B
// FooA
test.expectedRuntimeTypeInfoB().TypeMap["TYPE_KEY:b.c.d.FooB"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameB(), "FooB", "b.c.d.FooB"),
Fields: []mojom_types.StructField{}}}
// InterfaceB
test.expectedRuntimeTypeInfoB().TypeMap["TYPE_KEY:b.c.d.InterfaceB"] = &mojom_types.UserDefinedTypeInterfaceType{mojom_types.MojomInterface{
DeclData: newDeclData(test.fileNameB(), "InterfaceB", "b.c.d.InterfaceB"),
Methods: map[uint32]mojom_types.MojomMethod{
0: mojom_types.MojomMethod{
DeclData: newDeclDataO(0, -1, test.fileNameB(), "DoIt", ""),
Parameters: mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameB(), "DoIt-request", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: newDeclDataO(0, -1, test.fileNameB(), "x", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("a.b.c.FooA"), stringPointer("TYPE_KEY:a.b.c.FooA")}},
},
},
},
ResponseParams: &mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameB(), "DoIt-response", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: newDeclDataO(0, -1, test.fileNameB(), "y", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
true, false, stringPointer("FooB"), stringPointer("TYPE_KEY:b.c.d.FooB")}},
},
},
},
},
},
}}
test.endTestCase()
}
/////////////////////////////////////////////////////////////
// Test Case: Two interfaces: One of them top-level.
/////////////////////////////////////////////////////////////
{
contentsA := `
module a.b.c;
struct FooA{
};
[ServiceName = "AwesomeService"]
interface InterfaceA {
DoIt(FooA x) => (b.c.d.FooB? y);
};
`
contentsB := `
module b.c.d;
struct FooB{
};
interface InterfaceB {
DoIt(a.b.c.FooA x) => (FooB? y);
};
`
test.addTestCase(contentsA, contentsB)
// Services for file A
test.expectedRuntimeTypeInfoA().Services["AwesomeService"] = "TYPE_KEY:a.b.c.InterfaceA"
// TypeMap for file A
// FooA
test.expectedRuntimeTypeInfoA().TypeMap["TYPE_KEY:a.b.c.FooA"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameA(), "FooA", "a.b.c.FooA"),
Fields: []mojom_types.StructField{}}}
// InterfaceA
test.expectedRuntimeTypeInfoA().TypeMap["TYPE_KEY:a.b.c.InterfaceA"] = &mojom_types.UserDefinedTypeInterfaceType{mojom_types.MojomInterface{
DeclData: newDeclDataA(test.fileNameA(), "InterfaceA", "a.b.c.InterfaceA",
&[]mojom_types.Attribute{{"ServiceName", &mojom_types.LiteralValueStringValue{"AwesomeService"}}}),
ServiceName: stringPointer("AwesomeService"),
Methods: map[uint32]mojom_types.MojomMethod{
0: mojom_types.MojomMethod{
DeclData: newDeclDataO(0, -1, test.fileNameA(), "DoIt", ""),
Parameters: mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameA(), "DoIt-request", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: newDeclDataO(0, -1, test.fileNameA(), "x", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("FooA"), stringPointer("TYPE_KEY:a.b.c.FooA")}},
},
},
},
ResponseParams: &mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameA(), "DoIt-response", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: newDeclDataO(0, -1, test.fileNameA(), "y", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
true, false, stringPointer("b.c.d.FooB"), stringPointer("TYPE_KEY:b.c.d.FooB")}},
},
},
},
},
},
}}
////////////////////////////////////////////////////////////////////////
// TypeMap for file B
// FooA
test.expectedRuntimeTypeInfoB().TypeMap["TYPE_KEY:b.c.d.FooB"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameB(), "FooB", "b.c.d.FooB"),
Fields: []mojom_types.StructField{}}}
// InterfaceB
test.expectedRuntimeTypeInfoB().TypeMap["TYPE_KEY:b.c.d.InterfaceB"] = &mojom_types.UserDefinedTypeInterfaceType{mojom_types.MojomInterface{
DeclData: newDeclData(test.fileNameB(), "InterfaceB", "b.c.d.InterfaceB"),
Methods: map[uint32]mojom_types.MojomMethod{
0: mojom_types.MojomMethod{
DeclData: newDeclDataO(0, -1, test.fileNameB(), "DoIt", ""),
Parameters: mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameB(), "DoIt-request", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: newDeclDataO(0, -1, test.fileNameB(), "x", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("a.b.c.FooA"), stringPointer("TYPE_KEY:a.b.c.FooA")}},
},
},
},
ResponseParams: &mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameB(), "DoIt-response", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: newDeclDataO(0, -1, test.fileNameB(), "y", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
true, false, stringPointer("FooB"), stringPointer("TYPE_KEY:b.c.d.FooB")}},
},
},
},
},
},
}}
test.endTestCase()
}
/////////////////////////////////////////////////////////////
// Test Case: Same as above with extra attributes.
/////////////////////////////////////////////////////////////
{
contentsA := `
module a.b.c;
struct FooA{
};
[Color="RED", ServiceName = 7, ServiceName = "AwesomeService", Height=10.1]
interface InterfaceA {
DoIt(FooA x) => (b.c.d.FooB? y);
};
`
contentsB := `
module b.c.d;
struct FooB{
};
[ServiceName = 42]
interface InterfaceB {
DoIt(a.b.c.FooA x) => (FooB? y);
};
`
test.addTestCase(contentsA, contentsB)
// Services for file A
test.expectedRuntimeTypeInfoA().Services["AwesomeService"] = "TYPE_KEY:a.b.c.InterfaceA"
// FooA
test.expectedRuntimeTypeInfoA().TypeMap["TYPE_KEY:a.b.c.FooA"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameA(), "FooA", "a.b.c.FooA"),
Fields: []mojom_types.StructField{}}}
// InterfaceA
test.expectedRuntimeTypeInfoA().TypeMap["TYPE_KEY:a.b.c.InterfaceA"] = &mojom_types.UserDefinedTypeInterfaceType{mojom_types.MojomInterface{
DeclData: newDeclDataA(test.fileNameA(), "InterfaceA", "a.b.c.InterfaceA",
&[]mojom_types.Attribute{
{"Color", &mojom_types.LiteralValueStringValue{"RED"}},
{"ServiceName", &mojom_types.LiteralValueInt8Value{7}},
{"ServiceName", &mojom_types.LiteralValueStringValue{"AwesomeService"}},
{"Height", &mojom_types.LiteralValueDoubleValue{10.1}}}),
ServiceName: stringPointer("AwesomeService"),
Methods: map[uint32]mojom_types.MojomMethod{
0: mojom_types.MojomMethod{
DeclData: newDeclDataO(0, -1, test.fileNameA(), "DoIt", ""),
Parameters: mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameA(), "DoIt-request", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: newDeclDataO(0, -1, test.fileNameA(), "x", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("FooA"), stringPointer("TYPE_KEY:a.b.c.FooA")}},
},
},
},
ResponseParams: &mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameA(), "DoIt-response", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: newDeclDataO(0, -1, test.fileNameA(), "y", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
true, false, stringPointer("b.c.d.FooB"), stringPointer("TYPE_KEY:b.c.d.FooB")}},
},
},
},
},
},
}}
////////////////////////////////////////////////////////////////////////
// TypeMap for file B
// FooA
test.expectedRuntimeTypeInfoB().TypeMap["TYPE_KEY:b.c.d.FooB"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameB(), "FooB", "b.c.d.FooB"),
Fields: []mojom_types.StructField{}}}
// InterfaceB
test.expectedRuntimeTypeInfoB().TypeMap["TYPE_KEY:b.c.d.InterfaceB"] = &mojom_types.UserDefinedTypeInterfaceType{mojom_types.MojomInterface{
DeclData: newDeclDataA(test.fileNameB(), "InterfaceB", "b.c.d.InterfaceB",
&[]mojom_types.Attribute{{"ServiceName", &mojom_types.LiteralValueInt8Value{42}}}),
Methods: map[uint32]mojom_types.MojomMethod{
0: mojom_types.MojomMethod{
DeclData: newDeclDataO(0, -1, test.fileNameB(), "DoIt", ""),
Parameters: mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameB(), "DoIt-request", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: newDeclDataO(0, -1, test.fileNameB(), "x", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("a.b.c.FooA"), stringPointer("TYPE_KEY:a.b.c.FooA")}},
},
},
},
ResponseParams: &mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameB(), "DoIt-response", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: newDeclDataO(0, -1, test.fileNameB(), "y", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
true, false, stringPointer("FooB"), stringPointer("TYPE_KEY:b.c.d.FooB")}},
},
},
},
},
},
}}
test.endTestCase()
}
/////////////////////////////////////////////////////////////
// Test Case: Additional reachable types.
/////////////////////////////////////////////////////////////
{
contentsA := `
module a.b.c;
struct FooA{
};
[ServiceName = "AwesomeService"]
interface InterfaceA {
DoIt(FooA x) => (b.c.d.FooB? y);
};
`
contentsB := `
module b.c.d;
enum Enum1{}; // This is in the CompleteTypeSet of InterfaceA
enum Enum2{}; // This is not.
struct FooB{
Enum1 x;
};
interface InterfaceB {
DoIt(a.b.c.FooA x) => (FooB? y, Enum2 z);
};
`
test.addTestCase(contentsA, contentsB)
// Services for file A
test.expectedRuntimeTypeInfoA().Services["AwesomeService"] = "TYPE_KEY:a.b.c.InterfaceA"
// TypeMap for file A
// FooA
test.expectedRuntimeTypeInfoA().TypeMap["TYPE_KEY:a.b.c.FooA"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameA(), "FooA", "a.b.c.FooA"),
Fields: []mojom_types.StructField{}}}
// InterfaceA
test.expectedRuntimeTypeInfoA().TypeMap["TYPE_KEY:a.b.c.InterfaceA"] = &mojom_types.UserDefinedTypeInterfaceType{mojom_types.MojomInterface{
DeclData: newDeclDataA(test.fileNameA(), "InterfaceA", "a.b.c.InterfaceA",
&[]mojom_types.Attribute{{"ServiceName", &mojom_types.LiteralValueStringValue{"AwesomeService"}}}),
ServiceName: stringPointer("AwesomeService"),
Methods: map[uint32]mojom_types.MojomMethod{
0: mojom_types.MojomMethod{
DeclData: newDeclDataO(0, -1, test.fileNameA(), "DoIt", ""),
Parameters: mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameA(), "DoIt-request", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: newDeclDataO(0, -1, test.fileNameA(), "x", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("FooA"), stringPointer("TYPE_KEY:a.b.c.FooA")}},
},
},
},
ResponseParams: &mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameA(), "DoIt-response", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: newDeclDataO(0, -1, test.fileNameA(), "y", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
true, false, stringPointer("b.c.d.FooB"), stringPointer("TYPE_KEY:b.c.d.FooB")}},
},
},
},
},
},
}}
////////////////////////////////////////////////////////////////////////
// TypeMap for file B
// Enum1
test.expectedRuntimeTypeInfoB().TypeMap["TYPE_KEY:b.c.d.Enum1"] = &mojom_types.UserDefinedTypeEnumType{mojom_types.MojomEnum{
DeclData: newDeclData(test.fileNameB(), "Enum1", "b.c.d.Enum1"),
Values: []mojom_types.EnumValue{},
}}
// Enum2
test.expectedRuntimeTypeInfoB().TypeMap["TYPE_KEY:b.c.d.Enum2"] = &mojom_types.UserDefinedTypeEnumType{mojom_types.MojomEnum{
DeclData: newDeclData(test.fileNameB(), "Enum2", "b.c.d.Enum2"),
Values: []mojom_types.EnumValue{},
}}
// FooA
test.expectedRuntimeTypeInfoB().TypeMap["TYPE_KEY:b.c.d.FooB"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameB(), "FooB", "b.c.d.FooB"),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: newDeclDataO(0, -1, test.fileNameB(), "x", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("Enum1"), stringPointer("TYPE_KEY:b.c.d.Enum1")}},
},
},
}}
// InterfaceB
test.expectedRuntimeTypeInfoB().TypeMap["TYPE_KEY:b.c.d.InterfaceB"] = &mojom_types.UserDefinedTypeInterfaceType{mojom_types.MojomInterface{
DeclData: newDeclData(test.fileNameB(), "InterfaceB", "b.c.d.InterfaceB"),
Methods: map[uint32]mojom_types.MojomMethod{
0: mojom_types.MojomMethod{
DeclData: newDeclDataO(0, -1, test.fileNameB(), "DoIt", ""),
Parameters: mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameB(), "DoIt-request", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: newDeclDataO(0, -1, test.fileNameB(), "x", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("a.b.c.FooA"), stringPointer("TYPE_KEY:a.b.c.FooA")}},
},
},
},
ResponseParams: &mojom_types.MojomStruct{
DeclData: newDeclData(test.fileNameB(), "DoIt-response", ""),
Fields: []mojom_types.StructField{
mojom_types.StructField{
DeclData: newDeclDataO(0, -1, test.fileNameB(), "y", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
true, false, stringPointer("FooB"), stringPointer("TYPE_KEY:b.c.d.FooB")}},
},
mojom_types.StructField{
DeclData: newDeclDataO(1, -1, test.fileNameB(), "z", ""),
Type: &mojom_types.TypeTypeReference{mojom_types.TypeReference{
false, false, stringPointer("Enum2"), stringPointer("TYPE_KEY:b.c.d.Enum2")}},
},
},
},
},
},
}}
test.endTestCase()
}
////////////////////////////////////////////////////////////
// Execute all of the test cases.
////////////////////////////////////////////////////////////
for i, c := range test.cases {
descriptor := mojom.NewMojomDescriptor()
fileNameA := fmt.Sprintf("file%dA", i)
fileNameB := fmt.Sprintf("file%dB", i)
// Parse file A.
parserA := parser.MakeParser(fileNameA, fileNameA, c.mojomContentsA, descriptor, nil)
parserA.Parse()
if !parserA.OK() {
t.Errorf("Parsing error for %s: %s", fileNameA, parserA.GetError().Error())
continue
}
// Parse file B.
parserB := parser.MakeParser(fileNameB, fileNameB, c.mojomContentsB, descriptor, nil)
parserB.Parse()
if !parserB.OK() {
t.Errorf("Parsing error for %s: %s", fileNameB, parserB.GetError().Error())
continue
}
// Resolve
if err := descriptor.Resolve(); err != nil {
t.Errorf("Resolve error for case %d: %s", i, err.Error())
continue
}
if err := descriptor.ComputeFinalData(); err != nil {
t.Errorf("ComputeFinalData error for case %d: %s", i, err.Error())
continue
}
if err := descriptor.DetectIllFoundedTypes(); err != nil {
t.Errorf("DetectIllFoundedTypes error for case %d: %s", i, err.Error())
continue
}
// Serialize
bytes, _, err := serialize(descriptor, false, false, false, true)
if err != nil {
t.Errorf("Serialization error for case %d: %s", i, err.Error())
continue
}
// Deserialize
decoder := bindings.NewDecoder(bytes, nil)
fileGraph := mojom_files.MojomFileGraph{}
fileGraph.Decode(decoder)
// Deserialize RuntimeTypeInfo A
runtimeTypeInfoA := deserializeRuntimeTypeInfo(*fileGraph.Files[fileNameA].SerializedRuntimeTypeInfo)
// Deserialize RuntimeTypeInfo B
runtimeTypeInfoB := deserializeRuntimeTypeInfo(*fileGraph.Files[fileNameB].SerializedRuntimeTypeInfo)
// Compare A
if err := compareTwoGoObjects(c.expectedRuntimeTypeInfoA, &runtimeTypeInfoA); err != nil {
t.Errorf("case %d A:\n%s", i, err.Error())
}
// Compare B
if err := compareTwoGoObjects(c.expectedRuntimeTypeInfoB, &runtimeTypeInfoB); err != nil {
t.Errorf("case %d B:\n%s", i, err.Error())
}
}
}
func deserializeRuntimeTypeInfo(base64String string) mojom_types.RuntimeTypeInfo {
compressedBytes, err := base64.StdEncoding.DecodeString(base64String)
if err != nil {
panic(fmt.Sprintf("Error while unencoding runtimeTypeInfo: %s", err.Error()))
}
reader, err2 := gzip.NewReader(bytes.NewBuffer(compressedBytes))
if err2 != nil {
panic(fmt.Sprintf("Error while decompressing runtimeTypeInfo: %s", err.Error()))
}
uncompressedBytes, err3 := ioutil.ReadAll(reader)
if err3 != nil {
panic(fmt.Sprintf("Error while decompressing runtimeTypeInfo: %s", err2.Error()))
}
if err = reader.Close(); err != nil {
panic(fmt.Sprintf("Error while decompressing runtimeTypeInfo: %s", err.Error()))
}
decoder := bindings.NewDecoder(uncompressedBytes, nil)
runtimeTypeInfo := mojom_types.RuntimeTypeInfo{}
runtimeTypeInfo.Decode(decoder)
return runtimeTypeInfo
}
// compareTwoGoObjects compares |expected| and |actual| and returns a non-nil
// error if they are not deeply equal. The error message contains a human-readable
// string containing a deep-print of expected and actual along with the substrings
// starting from the first character where they differ.
func compareTwoGoObjects(expected interface{}, actual interface{}) error {
if !reflect.DeepEqual(expected, actual) {
// Note(rudominer) The myfmt package is a local modification of the fmt package
// that does a deep printing that follows pointers for up to 50 levels.
// Thus expectedString and actualString should contain enough information to
// precisely capture the structure of expected and actual.
expectedString := myfmt.Sprintf("%#v", expected)
actualString := myfmt.Sprintf("%#v", actual)
if expectedString != actualString {
diffPos := -1
for i := 0; i < len(expectedString) && i < len(actualString); i++ {
if expectedString[i] != actualString[i] {
diffPos = i
break
}
}
mismatchExpected := ""
mismatchActual := ""
if diffPos > -1 {
mismatchExpected = expectedString[diffPos:]
mismatchActual = actualString[diffPos:]
}
return fmt.Errorf("*****\nexpected=\n*****\n%q\n*****\nactual=\n*****\n%q\n*****\n"+
"match failed at position %d: expected=\n*****\n%q\n******\nactual=\n*****\n%q\n******\n",
expectedString, actualString, diffPos, mismatchExpected, mismatchActual)
} else {
return fmt.Errorf("expected != actual but the two printed equal.")
}
}
return nil
}