Merge pull request #7787 from w3c/sync_3eb5712dc6551242cee9cf7b81a477fd762abeae

Don't require test type in wpt expectation manifest,
diff --git a/tools/wptrunner/README.rst b/tools/wptrunner/README.rst
index fc650ee..780518a 100644
--- a/tools/wptrunner/README.rst
+++ b/tools/wptrunner/README.rst
@@ -146,8 +146,6 @@
   example_default_key: example_value
 
   [filename.html]
-    type: testharness
-
     [subtest1]
       expected: FAIL
 
@@ -158,7 +156,6 @@
         FAIL
 
   [filename.html?query=something]
-    type: testharness
     disabled: bug12345
 
 The file consists of two elements, key-value pairs and
@@ -230,9 +227,6 @@
 `disabled`
   Any value indicates that the test is disabled.
 
-`type`
-  The test type e.g. `testharness`, `reftest`, or `wdspec`.
-
 `reftype`
   The type of comparison for reftests; either `==` or `!=`.
 
diff --git a/tools/wptrunner/wptrunner/manifestupdate.py b/tools/wptrunner/wptrunner/manifestupdate.py
index 07e623c..d67cfff 100644
--- a/tools/wptrunner/wptrunner/manifestupdate.py
+++ b/tools/wptrunner/wptrunner/manifestupdate.py
@@ -116,7 +116,7 @@
         self._from_file = True
 
     @classmethod
-    def create(cls, test_type, test_id):
+    def create(cls, test_id):
         """Create a TestNode corresponding to a given test
 
         :param test_type: The type of the test
@@ -127,14 +127,13 @@
         node = DataNode(name)
         self = cls(node)
 
-        self.set("type", test_type)
         self._from_file = False
         return self
 
     @property
     def is_empty(self):
-        required_keys = set(["type"])
-        if set(self._data.keys()) != required_keys:
+        ignore_keys = set(["type"])
+        if set(self._data.keys()) - ignore_keys:
             return False
         return all(child.is_empty for child in self.children)
 
diff --git a/tools/wptrunner/wptrunner/metadata.py b/tools/wptrunner/wptrunner/metadata.py
index 73f266f..4414258 100644
--- a/tools/wptrunner/wptrunner/metadata.py
+++ b/tools/wptrunner/wptrunner/metadata.py
@@ -231,14 +231,16 @@
     def suite_start(self, data):
         self.run_info = data["run_info"]
 
-    def test_id(self, id):
-        if type(id) in types.StringTypes:
-            return id
-        else:
-            return tuple(id)
+    def test_type(self, path):
+        for manifest in self.test_manifests.iterkeys():
+            tests = list(manifest.iterpath(path))
+            if len(tests):
+                assert all(test.item_type == tests[0].item_type for test in tests)
+                return tests[0].item_type
+        assert False
 
     def test_start(self, data):
-        test_id = self.test_id(data["test"])
+        test_id = data["test"]
         try:
             test_manifest, test = self.id_path_map[test_id]
             expected_node = self.expected_tree[test_manifest][test].get_test(test_id)
@@ -253,11 +255,10 @@
             self.tests_visited[test_id] = set()
 
     def test_status(self, data):
-        test_id = self.test_id(data["test"])
-        test = self.test_cache.get(test_id)
+        test = self.test_cache.get(data["test"])
         if test is None:
             return
-        test_cls = wpttest.manifest_test_cls[test.test_type]
+        test_cls = wpttest.manifest_test_cls[self.test_type(test.root.test_path)]
 
         subtest = test.get_subtest(data["subtest"])
 
@@ -271,11 +272,11 @@
         subtest.set_result(self.run_info, result)
 
     def test_end(self, data):
-        test_id = self.test_id(data["test"])
+        test_id = data["test"]
         test = self.test_cache.get(test_id)
         if test is None:
             return
-        test_cls = wpttest.manifest_test_cls[test.test_type]
+        test_cls = wpttest.manifest_test_cls[self.test_type(test.root.test_path)]
 
         if data["status"] == "SKIP":
             return
@@ -322,7 +323,7 @@
                                                property_order=property_order,
                                                boolean_properties=boolean_properties)
     for test in tests:
-        expected.append(manifestupdate.TestNode.create(test.item_type, test.id))
+        expected.append(manifestupdate.TestNode.create(test.id))
     return expected
 
 
@@ -346,6 +347,6 @@
     # Add tests that don't have expected data
     for test in tests:
         if not expected_manifest.has_test(test.id):
-            expected_manifest.append(manifestupdate.TestNode.create(test.item_type, test.id))
+            expected_manifest.append(manifestupdate.TestNode.create(test.id))
 
     return expected_manifest
diff --git a/tools/wptrunner/wptrunner/wptmanifest/serializer.py b/tools/wptrunner/wptrunner/wptmanifest/serializer.py
index 52203ab..3be2a6d 100644
--- a/tools/wptrunner/wptrunner/wptmanifest/serializer.py
+++ b/tools/wptrunner/wptrunner/wptmanifest/serializer.py
@@ -28,6 +28,8 @@
     def serialize(self, root):
         self.indent = 2
         rv = "\n".join(self.visit(root))
+        if not rv:
+            return rv
         if rv[-1] != "\n":
             rv = rv + "\n"
         return rv