Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 package serialization | |
| 6 | |
| 7 import ( | |
| 8 "fmt" | |
| 9 "mojo/public/go/bindings" | |
| 10 "mojom/mojom_parser/generated/mojom_files" | |
| 11 "mojom/mojom_parser/generated/mojom_types" | |
| 12 "mojom/mojom_parser/mojom" | |
| 13 "mojom/mojom_parser/parser" | |
| 14 "reflect" | |
| 15 "testing" | |
| 16 myfmt "third_party/golang/src/fmt" | |
| 17 ) | |
| 18 | |
| 19 // TestSingleFileSerialization uses a series of test cases in which the text of a .mojom | |
| 20 // file is specified and the expected MojomFileGraph is specified using Go struc t literals. | |
| 21 func TestSingleFileSerialization(t *testing.T) { | |
| 22 | |
| 23 type testCase struct { | |
| 24 fileName string | |
| 25 mojomContents string | |
| 26 lineAndcolumnNumbers bool | |
| 27 expectedGraph *mojom_files.MojomFileGraph | |
| 28 } | |
| 29 cases := make([]testCase, 0) | |
| 30 testCaseNum := 0 | |
| 31 var expectedGraph *mojom_files.MojomFileGraph | |
| 32 var expectedFile *mojom_files.MojomFile | |
| 33 var fileName string | |
| 34 | |
| 35 startTestCase := func(moduleNameSpace string) { | |
|
mattr
2015/11/10 19:26:49
I found this structure a bit confusing. You could
rudominer
2015/11/10 23:29:36
I have refactored the test to try to make it more
| |
| 36 fileName = fmt.Sprintf("file%d", testCaseNum) | |
| 37 expectedGraph = new(mojom_files.MojomFileGraph) | |
| 38 expectedGraph.Files = make(map[string]mojom_files.MojomFile) | |
| 39 expectedFile = new(mojom_files.MojomFile) | |
| 40 expectedFile.FileName = fileName | |
| 41 expectedFile.ModuleNamespace = new(string) | |
| 42 *expectedFile.ModuleNamespace = moduleNameSpace | |
| 43 expectedGraph.ResolvedTypes = make(map[string]mojom_types.UserDe finedType) | |
| 44 expectedGraph.ResolvedValues = make(map[string]mojom_types.UserD efinedValue) | |
| 45 // We don't want to bother with line and column numbers which ar e brittle. | |
| 46 lineAndcolumnNumbers := false | |
| 47 cases = append(cases, testCase{fileName, "", lineAndcolumnNumber s, expectedGraph}) | |
| 48 } | |
| 49 | |
| 50 endTestCase := func() { | |
| 51 expectedGraph.Files[fileName] = *expectedFile | |
| 52 testCaseNum += 1 | |
| 53 } | |
| 54 | |
| 55 newDeclData := func(shortName, fullIdentifier string) *mojom_types.Decla rationData { | |
| 56 return &mojom_types.DeclarationData{ | |
| 57 ShortName: newString(shortName), | |
| 58 FullIdentifier: newString(fullIdentifier), | |
| 59 DeclaredOrdinal: -1, | |
| 60 DeclarationOrder: -1, | |
| 61 SourceFileInfo: &mojom_types.SourceFileInfo{ | |
| 62 FileName: fileName, | |
| 63 }} | |
| 64 } | |
| 65 | |
| 66 //////////////////////////////////////////////////////////// | |
| 67 // Test Case | |
| 68 //////////////////////////////////////////////////////////// | |
| 69 startTestCase("mojom.test") | |
| 70 cases[testCaseNum].mojomContents = ` | |
| 71 [go_namespace="go.test", | |
| 72 lucky=true, | |
| 73 planet=EARTH] | |
| 74 module mojom.test; | |
| 75 | |
| 76 import "another.file"; | |
| 77 import "and.another.file"; | |
| 78 | |
| 79 const uint16 NUM_MAGI = 3; | |
| 80 | |
| 81 struct Foo{ | |
| 82 int32 x; | |
| 83 string y = "hello"; | |
| 84 string? z; | |
| 85 | |
| 86 enum Hats { | |
| 87 TOP, | |
| 88 COWBOY = NUM_MAGI | |
| 89 }; | |
| 90 };` | |
| 91 { | |
| 92 // Attributes | |
| 93 expectedFile.Attributes = &[]mojom_types.Attribute{ | |
| 94 {"go_namespace", "go.test"}, {"lucky", "true"}, {"planet ", "EARTH"}, | |
| 95 } | |
| 96 | |
| 97 // Imports | |
| 98 expectedFile.Imports = &[]string{ | |
| 99 "another.file.canonical", "and.another.file.canonical", | |
| 100 } | |
| 101 | |
| 102 // DeclaredMojomObjects | |
| 103 expectedFile.DeclaredMojomObjects.Structs = &[]string{"ooF.tset. mojom"} | |
| 104 expectedFile.DeclaredMojomObjects.TopLevelConstants = &[]string{ "IGAM_MUN.tset.mojom"} | |
| 105 | |
| 106 // Resolved Values | |
| 107 | |
| 108 // NUM_MAGI | |
| 109 expectedGraph.ResolvedValues["IGAM_MUN.tset.mojom"] = &mojom_typ es.UserDefinedValueDeclaredConstant{mojom_types.DeclaredConstant{ | |
| 110 DeclData: *newDeclData("NUM_MAGI", "mojom.test.NUM_MAGI" ), | |
| 111 Type: &mojom_types.TypeSimpleType{mojom_types.Simple Type_UinT16}, | |
| 112 Value: &mojom_types.ValueLiteralValue{&mojom_types.Li teralValueInt64Value{3}}, | |
| 113 }} | |
| 114 | |
| 115 // Hats.TOP | |
| 116 expectedGraph.ResolvedValues["POT.staH.ooF.tset.mojom"] = &mojom _types.UserDefinedValueEnumValue{mojom_types.EnumValue{ | |
| 117 DeclData: newDeclData("TOP", "mojom.test.Foo.Hats.TOP "), | |
| 118 EnumTypeKey: "staH.ooF.tset.mojom", | |
| 119 IntValue: -1, | |
| 120 }} | |
| 121 | |
| 122 // Hats.COWBOY | |
| 123 expectedGraph.ResolvedValues["YOBWOC.staH.ooF.tset.mojom"] = &mo jom_types.UserDefinedValueEnumValue{mojom_types.EnumValue{ | |
| 124 DeclData: newDeclData("COWBOY", "mojom.test.Foo.Hats. COWBOY"), | |
| 125 EnumTypeKey: "staH.ooF.tset.mojom", | |
| 126 IntValue: 3, | |
| 127 InitializerValue: &mojom_types.ValueUserValueReference{m ojom_types.UserValueReference{ | |
| 128 Identifier: "NUM_MAGI", | |
| 129 ValueKey: newString("IGAM_MUN.tset. mojom"), | |
| 130 ResolvedConcreteValue: &mojom_types.ValueLiteral Value{&mojom_types.LiteralValueInt64Value{3}}, | |
| 131 }}, | |
| 132 }} | |
| 133 | |
| 134 // ResolvedTypes | |
| 135 | |
| 136 // struct Foo | |
| 137 expectedGraph.ResolvedTypes["ooF.tset.mojom"] = &mojom_types.Use rDefinedTypeStructType{mojom_types.MojomStruct{ | |
| 138 DeclData: &mojom_types.DeclarationData{ | |
| 139 ShortName: newString("Foo"), | |
| 140 FullIdentifier: newString("mojom.test.Foo"), | |
| 141 DeclaredOrdinal: -1, | |
| 142 DeclarationOrder: -1, | |
| 143 SourceFileInfo: &mojom_types.SourceFileInfo{ | |
| 144 FileName: fileName, | |
| 145 }, | |
| 146 ContainedDeclarations: &mojom_types.ContainedDec larations{ | |
| 147 Enums: &[]string{"staH.ooF.tset.mojom"}} , | |
| 148 }, | |
| 149 Fields: []mojom_types.StructField{ | |
| 150 // field x | |
| 151 { | |
| 152 DeclData: newDeclData("x", ""), | |
| 153 Type: &mojom_types.TypeSimpleType{mo jom_types.SimpleType_InT32}, | |
| 154 }, | |
| 155 // field y | |
| 156 { | |
| 157 DeclData: newDeclData("y", ""), | |
| 158 Type: &mojom_types.TypeStringTyp e{mojom_types.StringType{false}}, | |
| 159 DefaultValue: &mojom_types.DefaultFieldV alueValue{&mojom_types.ValueLiteralValue{&mojom_types.LiteralValueStringValue{"h ello"}}}, | |
| 160 }, | |
| 161 // field z | |
| 162 { | |
| 163 DeclData: newDeclData("z", ""), | |
| 164 Type: &mojom_types.TypeStringType{mo jom_types.StringType{true}}, | |
| 165 }, | |
| 166 }, | |
| 167 }} | |
| 168 | |
| 169 // enum Hats | |
| 170 expectedGraph.ResolvedTypes["staH.ooF.tset.mojom"] = &mojom_type s.UserDefinedTypeEnumType{mojom_types.MojomEnum{ | |
| 171 DeclData: newDeclData("Hats", "mojom.test.Foo.Hats"), | |
| 172 Values: []mojom_types.EnumValue{ | |
| 173 // Note(rudominer) It is a bug that we need to c opy the enum values here. | |
| 174 // See https://github.com/domokit/mojo/issues/51 3. | |
| 175 // value TOP | |
| 176 expectedGraph.ResolvedValues["POT.staH.ooF.tset. mojom"].(*mojom_types.UserDefinedValueEnumValue).Value, | |
| 177 // value COWBOY | |
| 178 expectedGraph.ResolvedValues["YOBWOC.staH.ooF.ts et.mojom"].(*mojom_types.UserDefinedValueEnumValue).Value, | |
| 179 }, | |
| 180 }} | |
| 181 } | |
| 182 | |
| 183 endTestCase() | |
| 184 | |
| 185 //////////////////////////////////////////////////////////// | |
| 186 // Execute all of the test cases. | |
| 187 //////////////////////////////////////////////////////////// | |
| 188 for _, c := range cases { | |
| 189 // Parse and resolve the mojom input. | |
| 190 descriptor := mojom.NewMojomDescriptor() | |
| 191 parser := parser.MakeParser(c.fileName, c.mojomContents, descrip tor) | |
| 192 parser.Parse() | |
| 193 if !parser.OK() { | |
| 194 t.Errorf("Parsing error for %s: %s", c.fileName, parser. GetError().Error()) | |
| 195 continue | |
| 196 } | |
| 197 if err := descriptor.Resolve(); err != nil { | |
| 198 t.Errorf("Resolve error for %s: %s", c.fileName, err.Err or()) | |
| 199 continue | |
| 200 } | |
| 201 if err := descriptor.ComputeEnumValueIntegers(); err != nil { | |
| 202 t.Errorf("ComputeEnumValueIntegers error for %s: %s", c. fileName, err.Error()) | |
| 203 continue | |
| 204 } | |
| 205 if err := descriptor.ComputeDataForGenerators(); err != nil { | |
| 206 t.Errorf("ComputeDataForGenerators error for %s: %s", c. fileName, err.Error()) | |
| 207 continue | |
| 208 } | |
| 209 | |
| 210 // Simulate setting the canonical file name for the imported fil es. In real operation | |
| 211 // this step is done in parser_driver.go when each of the import ed files are parsed. | |
| 212 mojomFile := parser.GetMojomFile() | |
| 213 if mojomFile.Imports != nil { | |
| 214 for _, imp := range mojomFile.Imports { | |
| 215 imp.CanonicalFileName = fmt.Sprintf("%s.canonica l", imp.SpecifiedName) | |
| 216 } | |
| 217 } | |
| 218 | |
| 219 // Serialize | |
| 220 EmitLineAndColumnNumbers = c.lineAndcolumnNumbers | |
| 221 bytes, err := Serialize(descriptor) | |
| 222 if err != nil { | |
| 223 t.Errorf("Serialization error for %s: %s", c.fileName, e rr.Error()) | |
| 224 continue | |
| 225 } | |
| 226 | |
| 227 // Deserialize | |
| 228 decoder := bindings.NewDecoder(bytes, nil) | |
| 229 fileGraph := mojom_files.MojomFileGraph{} | |
| 230 fileGraph.Decode(decoder) | |
| 231 | |
| 232 // Compare | |
| 233 if err := compareFileGraphs(c.expectedGraph, &fileGraph); err != nil { | |
| 234 t.Errorf("%s:\n%s", c.fileName, err.Error()) | |
| 235 continue | |
| 236 } | |
| 237 } | |
| 238 } | |
| 239 | |
| 240 // compareFileGraphs compares |expected| and |actual| and returns a non-nil | |
| 241 // error if they are not deeply equal. The error message contains a human-readab le | |
| 242 // string containing a deep-print of expected and actual along with the substrin gs | |
| 243 // starting from the first character where they differ. | |
| 244 func compareFileGraphs(expected *mojom_files.MojomFileGraph, actual *mojom_files .MojomFileGraph) error { | |
| 245 if !reflect.DeepEqual(expected, actual) { | |
| 246 // Note(rudominer) The myfmt package is a local modification of the fmt package | |
| 247 // that does a deep printing that follows pointers for up to 50 levels. | |
| 248 // Thus expectedString and actualString should contain enough in formation to | |
| 249 // precisely capture the structure of expected and actual. | |
| 250 expectedString := myfmt.Sprintf("%+v", expected) | |
| 251 actualString := myfmt.Sprintf("%+v", actual) | |
| 252 if expectedString != actualString { | |
| 253 diffPos := -1 | |
| 254 for i := 0; i < len(expectedString) && i < len(actualStr ing); i++ { | |
| 255 if expectedString[i] != actualString[i] { | |
| 256 diffPos = i | |
| 257 break | |
| 258 } | |
| 259 } | |
| 260 mismatchExpected := "" | |
| 261 mismatchActual := "" | |
| 262 if diffPos > -1 { | |
| 263 mismatchExpected = expectedString[diffPos:] | |
| 264 mismatchActual = actualString[diffPos:] | |
| 265 } | |
| 266 return fmt.Errorf("*****\nexpected=\n*****\n%q\n*****\na ctual=\n*****\n%q\n*****\n"+ | |
| 267 "match failed at position %d: expected=\n*****\n %s\n******\nactual=\n*****\n%s\n******\n", | |
| 268 expectedString, actualString, diffPos, mismatchE xpected, mismatchActual) | |
| 269 } else { | |
| 270 return fmt.Errorf("expected != actual but the two printe d equal.") | |
| 271 } | |
| 272 } | |
| 273 return nil | |
| 274 } | |
| OLD | NEW |