Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(185)

Unified Diff: mojom/mojom_parser/serialization/serialization_test.go

Issue 1421193003: New Mojom Parser: Serialization. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Refactors TestSingleFileSerialization. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mojom/mojom_parser/serialization/serialization.go ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojom/mojom_parser/serialization/serialization_test.go
diff --git a/mojom/mojom_parser/serialization/serialization_test.go b/mojom/mojom_parser/serialization/serialization_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..b8ccaf0fd2eda5738cbd84176c04557ff9e8511a
--- /dev/null
+++ b/mojom/mojom_parser/serialization/serialization_test.go
@@ -0,0 +1,301 @@
+// 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 (
+ "fmt"
+ "mojo/public/go/bindings"
+ "mojom/mojom_parser/generated/mojom_files"
+ "mojom/mojom_parser/generated/mojom_types"
+ "mojom/mojom_parser/mojom"
+ "mojom/mojom_parser/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().ModuleNamespace = newString(moduleNameSpace)
+
+ test.expectedGraph().ResolvedTypes = make(map[string]mojom_types.UserDefinedType)
+ test.expectedGraph().ResolvedValues = make(map[string]mojom_types.UserDefinedValue)
+}
+
+// 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
+}
+
+// newDeclData constructs a new DeclarationData with the given data.
+func (test *singleFileTest) newDeclData(shortName, fullIdentifier string) *mojom_types.DeclarationData {
+ return &mojom_types.DeclarationData{
+ ShortName: newString(shortName),
+ FullIdentifier: newString(fullIdentifier),
+ DeclaredOrdinal: -1,
+ DeclarationOrder: -1,
+ SourceFileInfo: &mojom_types.SourceFileInfo{
+ FileName: test.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
+ ////////////////////////////////////////////////////////////
+ {
+
+ 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;
+ string y = "hello";
+ string? z;
+
+ enum Hats {
+ TOP,
+ COWBOY = NUM_MAGI
+ };
+ };`
+
+ test.addTestCase("mojom.test", contents)
+
+ // Attributes
+ test.expectedFile().Attributes = &[]mojom_types.Attribute{
+ {"go_namespace", "go.test"}, {"lucky", "true"}, {"planet", "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 Values
+
+ // NUM_MAGI
+ test.expectedGraph().ResolvedValues["TYPE_KEY:mojom.test.NUM_MAGI"] = &mojom_types.UserDefinedValueDeclaredConstant{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.LiteralValueInt64Value{3}},
+ }}
+
+ // Hats.TOP
+ test.expectedGraph().ResolvedValues["TYPE_KEY:mojom.test.Foo.Hats.TOP"] = &mojom_types.UserDefinedValueEnumValue{mojom_types.EnumValue{
+ DeclData: test.newDeclData("TOP", "mojom.test.Foo.Hats.TOP"),
+ EnumTypeKey: "TYPE_KEY:mojom.test.Foo.Hats",
+ IntValue: -1,
+ }}
+
+ // Hats.COWBOY
+ test.expectedGraph().ResolvedValues["TYPE_KEY:mojom.test.Foo.Hats.COWBOY"] = &mojom_types.UserDefinedValueEnumValue{mojom_types.EnumValue{
+ DeclData: test.newDeclData("COWBOY", "mojom.test.Foo.Hats.COWBOY"),
+ EnumTypeKey: "TYPE_KEY:mojom.test.Foo.Hats",
+ IntValue: 3,
+ InitializerValue: &mojom_types.ValueUserValueReference{mojom_types.UserValueReference{
+ Identifier: "NUM_MAGI",
+ ValueKey: newString("TYPE_KEY:mojom.test.NUM_MAGI"),
+ ResolvedConcreteValue: &mojom_types.ValueLiteralValue{&mojom_types.LiteralValueInt64Value{3}},
+ }},
+ }}
+
+ // ResolvedTypes
+
+ // struct Foo
+ test.expectedGraph().ResolvedTypes["TYPE_KEY:mojom.test.Foo"] = &mojom_types.UserDefinedTypeStructType{mojom_types.MojomStruct{
+ DeclData: &mojom_types.DeclarationData{
+ ShortName: newString("Foo"),
+ FullIdentifier: newString("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.newDeclData("x", ""),
+ Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_InT32},
+ },
+ // field y
+ {
+ DeclData: test.newDeclData("y", ""),
+ Type: &mojom_types.TypeStringType{mojom_types.StringType{false}},
+ DefaultValue: &mojom_types.DefaultFieldValueValue{&mojom_types.ValueLiteralValue{&mojom_types.LiteralValueStringValue{"hello"}}},
+ },
+ // field z
+ {
+ DeclData: test.newDeclData("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.newDeclData("Hats", "mojom.test.Foo.Hats"),
+ Values: []mojom_types.EnumValue{
+ // Note(rudominer) It is a bug that we need to copy the enum values here.
+ // See https://github.com/domokit/mojo/issues/513.
+ // value TOP
+ test.expectedGraph().ResolvedValues["TYPE_KEY:mojom.test.Foo.Hats.TOP"].(*mojom_types.UserDefinedValueEnumValue).Value,
+ // value COWBOY
+ test.expectedGraph().ResolvedValues["TYPE_KEY:mojom.test.Foo.Hats.COWBOY"].(*mojom_types.UserDefinedValueEnumValue).Value,
+ },
+ }}
+
+ 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.mojomContents, descriptor)
+ 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.ComputeEnumValueIntegers(); err != nil {
+ t.Errorf("ComputeEnumValueIntegers error for %s: %s", c.fileName, err.Error())
+ continue
+ }
+ if err := descriptor.ComputeDataForGenerators(); err != nil {
+ t.Errorf("ComputeDataForGenerators 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
+ EmitLineAndColumnNumbers = c.lineAndcolumnNumbers
+ bytes, err := Serialize(descriptor)
+ 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 := compareFileGraphs(c.expectedGraph, &fileGraph); err != nil {
+ t.Errorf("%s:\n%s", c.fileName, err.Error())
+ continue
+ }
+ }
+}
+
+// compareFileGraphs 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 compareFileGraphs(expected *mojom_files.MojomFileGraph, actual *mojom_files.MojomFileGraph) 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%s\n******\nactual=\n*****\n%s\n******\n",
+ expectedString, actualString, diffPos, mismatchExpected, mismatchActual)
+ } else {
+ return fmt.Errorf("expected != actual but the two printed equal.")
+ }
+ }
+ return nil
+}
« no previous file with comments | « mojom/mojom_parser/serialization/serialization.go ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698