OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package parser | 5 package parser |
6 | 6 |
7 import ( | 7 import ( |
8 "fmt" | 8 "fmt" |
9 "mojom/mojom_tool/mojom" | 9 "mojom/mojom_tool/mojom" |
10 "mojom/mojom_tool/parser" | 10 "mojom/mojom_tool/parser" |
(...skipping 1066 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1077 } | 1077 } |
1078 | 1078 |
1079 if c.testFunc != nil { | 1079 if c.testFunc != nil { |
1080 if err := c.testFunc(descriptor); err != nil { | 1080 if err := c.testFunc(descriptor); err != nil { |
1081 t.Errorf("%s:\n%s", fileName, err.Error()) | 1081 t.Errorf("%s:\n%s", fileName, err.Error()) |
1082 continue | 1082 continue |
1083 } | 1083 } |
1084 } | 1084 } |
1085 } | 1085 } |
1086 } | 1086 } |
1087 | |
1088 //////////////////////////////////////////////// | |
1089 /// TestFindReachableTypes | |
1090 //////////////////////////////////////////////// | |
1091 | |
1092 // typeGraphTestCase stores the data for one test case. | |
1093 type typeGraphTestCase struct { | |
1094 mojomContents string | |
1095 typeToSearch string | |
1096 expectedReachableTypes []string | |
1097 } | |
1098 | |
1099 // typeGraphTest contains a series of test cases. | |
1100 type typeGraphTest struct { | |
1101 cases []typeGraphTestCase | |
1102 } | |
1103 | |
1104 // addTestCase() should be invoked at the start of a case in TestFindReachableTy
pes. | |
1105 func (test *typeGraphTest) addTestCase(contents, typeToSearch string, expectedRe
achableTypes []string) { | |
1106 test.cases = append(test.cases, typeGraphTestCase{contents, typeToSearch
, expectedReachableTypes}) | |
1107 } | |
1108 | |
1109 // TestFindReachableTypes() iterates through a series of test cases. | |
1110 // For each case we expect for parsing and resolution to succeed. Then we | |
1111 // invoke FindReachableTypes() on |typeToSearch| and compare the result | |
1112 // to |expectedReachableTypes|. | |
1113 func TestFindReachableTypes(t *testing.T) { | |
1114 test := typeGraphTest{} | |
1115 | |
1116 //////////////////////////////////////////////////////////// | |
1117 // Test Case | |
1118 //////////////////////////////////////////////////////////// | |
1119 { | |
1120 contents := ` | |
1121 struct Struct1{ | |
1122 }; | |
1123 | |
1124 struct Struct2{ | |
1125 Struct1 x; | |
1126 }; | |
1127 | |
1128 struct Struct3{ | |
1129 Struct2 x; | |
1130 }; | |
1131 | |
1132 struct Struct4{ | |
1133 Struct3 x; | |
1134 }; | |
1135 | |
1136 union Union1 { | |
1137 Struct3 x; | |
1138 Struct2 y; | |
1139 }; | |
1140 | |
1141 union Union2 { | |
1142 Struct2 x; | |
1143 }; | |
1144 ` | |
1145 test.addTestCase(contents, | |
1146 "Struct4", | |
1147 []string{"Struct1", "Struct2", "Struct3", "Struct4"}, | |
1148 ) | |
1149 | |
1150 test.addTestCase(contents, | |
1151 "Union1", | |
1152 []string{"Union1", "Struct1", "Struct2", "Struct3"}, | |
1153 ) | |
1154 | |
1155 test.addTestCase(contents, | |
1156 "Union2", | |
1157 []string{"Union2", "Struct1", "Struct2"}, | |
1158 ) | |
1159 } | |
1160 | |
1161 //////////////////////////////////////////////////////////// | |
1162 // Test Case | |
1163 //////////////////////////////////////////////////////////// | |
1164 { | |
1165 contents := ` | |
1166 struct Struct1{ | |
1167 Struct4 x; | |
1168 }; | |
1169 | |
1170 struct Struct2{ | |
1171 Struct1 x; | |
1172 }; | |
1173 | |
1174 struct Struct3{ | |
1175 Struct2 x; | |
1176 }; | |
1177 | |
1178 struct Struct4{ | |
1179 Struct3 x; | |
1180 }; | |
1181 | |
1182 union Union1 { | |
1183 Struct2 x; | |
1184 }; | |
1185 ` | |
1186 | |
1187 test.addTestCase(contents, | |
1188 "Union1", | |
1189 []string{"Union1", "Struct1", "Struct2", "Struct3", "Str
uct4"}, | |
1190 ) | |
1191 } | |
1192 | |
1193 //////////////////////////////////////////////////////////// | |
1194 // Test Cases | |
1195 //////////////////////////////////////////////////////////// | |
1196 { | |
1197 contents := ` | |
1198 | |
1199 enum Height { | |
1200 SHORT, TALL | |
1201 }; | |
1202 | |
1203 struct Struct1{ | |
1204 enum Color { | |
1205 RED, BLUE | |
1206 }; | |
1207 }; | |
1208 | |
1209 struct Struct2{ | |
1210 const Struct1.Color FAVORITE = RED; | |
1211 }; | |
1212 ` | |
1213 | |
1214 test.addTestCase(contents, | |
1215 "Struct1", | |
1216 []string{"Struct1", "Struct1.Color"}, | |
1217 ) | |
1218 | |
1219 test.addTestCase(contents, | |
1220 "Struct2", | |
1221 []string{"Struct2", "Struct1.Color"}, | |
1222 ) | |
1223 } | |
1224 | |
1225 //////////////////////////////////////////////////////////// | |
1226 // Test Cases | |
1227 //////////////////////////////////////////////////////////// | |
1228 { | |
1229 contents := ` | |
1230 enum Color { | |
1231 RED, BLUE | |
1232 }; | |
1233 | |
1234 enum Height { | |
1235 SHORT, TALL | |
1236 }; | |
1237 | |
1238 struct Struct1{}; | |
1239 struct Struct2{}; | |
1240 | |
1241 interface Interface1 { | |
1242 const Color FAVORITE_COLOR = RED; | |
1243 | |
1244 Foo(int32 x) => (string y); | |
1245 }; | |
1246 | |
1247 interface Interface2 { | |
1248 Foo(int32 x) => (Struct1 y); | |
1249 Bar(string x); | |
1250 }; | |
1251 ` | |
1252 | |
1253 test.addTestCase(contents, | |
1254 "Interface1", | |
1255 []string{"Interface1", "Color"}, | |
1256 ) | |
1257 | |
1258 test.addTestCase(contents, | |
1259 "Interface2", | |
1260 []string{"Interface2", "Struct1"}, | |
1261 ) | |
1262 } | |
1263 | |
1264 //////////////////////////////////////////////////////////// | |
1265 // Test Cases | |
1266 //////////////////////////////////////////////////////////// | |
1267 | |
1268 { | |
1269 contents := ` | |
1270 enum Color { | |
1271 RED, BLUE | |
1272 }; | |
1273 | |
1274 enum Height { | |
1275 SHORT, TALL | |
1276 }; | |
1277 | |
1278 struct Struct1{}; | |
1279 struct Struct2{}; | |
1280 | |
1281 interface Interface1 { | |
1282 const Color FAVORITE_COLOR = RED; | |
1283 | |
1284 Foo(map<Height, int8> x) => (string y); | |
1285 }; | |
1286 | |
1287 interface Interface2 { | |
1288 Foo(int32 x) => (array<Struct1?> y); | |
1289 }; | |
1290 ` | |
1291 | |
1292 test.addTestCase(contents, | |
1293 "Interface1", | |
1294 []string{"Interface1", "Color", "Height"}, | |
1295 ) | |
1296 | |
1297 test.addTestCase(contents, | |
1298 "Interface2", | |
1299 []string{"Interface2", "Struct1"}, | |
1300 ) | |
1301 } | |
1302 | |
1303 //////////////////////////////////////////////////////////// | |
1304 // Test Cases | |
1305 //////////////////////////////////////////////////////////// | |
1306 | |
1307 { | |
1308 contents := ` | |
1309 enum Color { | |
1310 RED, BLUE | |
1311 }; | |
1312 | |
1313 enum Height { | |
1314 SHORT, TALL | |
1315 }; | |
1316 | |
1317 struct Struct1{}; | |
1318 struct Struct2{}; | |
1319 | |
1320 interface Interface1 { | |
1321 const Color FAVORITE_COLOR = RED; | |
1322 | |
1323 Foo(int32 x) => (string y); | |
1324 Bar(map<string, Height> z) => (); | |
1325 }; | |
1326 | |
1327 interface Interface2 { | |
1328 Foo(int32 x) => (map<Height, Struct1?> y); | |
1329 }; | |
1330 ` | |
1331 | |
1332 test.addTestCase(contents, | |
1333 "Interface1", | |
1334 []string{"Interface1", "Color", "Height"}, | |
1335 ) | |
1336 | |
1337 test.addTestCase(contents, | |
1338 "Interface2", | |
1339 []string{"Interface2", "Height", "Struct1"}, | |
1340 ) | |
1341 } | |
1342 | |
1343 //////////////////////////////////////////////////////////// | |
1344 // Execute all of the test cases. | |
1345 //////////////////////////////////////////////////////////// | |
1346 for i, c := range test.cases { | |
1347 // Parse and resolve the mojom input. | |
1348 descriptor := mojom.NewMojomDescriptor() | |
1349 fileName := fmt.Sprintf("file%d", i) | |
1350 parser := parser.MakeParser(fileName, fileName, c.mojomContents,
descriptor, nil) | |
1351 parser.Parse() | |
1352 if !parser.OK() { | |
1353 t.Errorf("Parsing error for %s: %s", fileName, parser.Ge
tError().Error()) | |
1354 continue | |
1355 } | |
1356 err := descriptor.Resolve() | |
1357 if err != nil { | |
1358 t.Errorf("Resolution failed for test case %d: %s", i, er
r.Error()) | |
1359 continue | |
1360 } | |
1361 | |
1362 userDefinedType := descriptor.TypesByKey[mojom.ComputeTypeKey(c.
typeToSearch)] | |
1363 result := userDefinedType.FindReachableTypes() | |
1364 if err := compareTypeSets(descriptor, c.expectedReachableTypes,
result); err != nil { | |
1365 t.Errorf("Case %d, unexpected typeset for %s: %s\n", i,
c.typeToSearch, err.Error()) | |
1366 continue | |
1367 } | |
1368 } | |
1369 } | |
1370 | |
1371 func compareTypeSets(descriptor *mojom.MojomDescriptor, expectedTypeNames, actua
lTypeKeys []string) error { | |
1372 expectedSet := userDefinedTypeSet(descriptor, expectedTypeNames, false) | |
1373 actualSet := userDefinedTypeSet(descriptor, actualTypeKeys, true) | |
1374 return expectedSet.Compare(&actualSet) | |
1375 } | |
1376 | |
1377 func userDefinedTypeSet(descriptor *mojom.MojomDescriptor, types []string, types
AreKeys bool) mojom.UserDefinedTypeSet { | |
1378 typeSet := mojom.MakeUserDefinedTypeSet() | |
1379 for _, t := range types { | |
1380 if t == "" { | |
1381 panic("Found empty type in types array.") | |
1382 } | |
1383 var typeKey string | |
1384 if typesAreKeys { | |
1385 typeKey = t | |
1386 } else { | |
1387 typeKey = mojom.ComputeTypeKey(t) | |
1388 } | |
1389 userDefinedType := descriptor.TypesByKey[typeKey] | |
1390 if userDefinedType == nil { | |
1391 panic(fmt.Sprintf("No type found for: %s", t)) | |
1392 } | |
1393 typeSet.Add(userDefinedType) | |
1394 } | |
1395 return typeSet | |
1396 } | |
OLD | NEW |