1import os 2from six.moves.urllib.parse import urljoin 3from abc import ABCMeta, abstractmethod, abstractproperty 4 5 6def get_source_file(source_files, tests_root, manifest, path): 7 def make_new(): 8 from .sourcefile import SourceFile 9 10 return SourceFile(tests_root, path, manifest.url_base) 11 12 if source_files is None: 13 return make_new() 14 15 if path not in source_files: 16 source_files[path] = make_new() 17 18 return source_files[path] 19 20 21class ManifestItem(object): 22 __metaclass__ = ABCMeta 23 24 item_type = None 25 26 def __init__(self, source_file, manifest=None): 27 self.manifest = manifest 28 self.source_file = source_file 29 30 @abstractproperty 31 def id(self): 32 """The test's id (usually its url)""" 33 pass 34 35 @property 36 def path(self): 37 """The test path relative to the test_root""" 38 return self.source_file.rel_path 39 40 @property 41 def https(self): 42 return "https" in self.source_file.meta_flags 43 44 def key(self): 45 """A unique identifier for the test""" 46 return (self.item_type, self.id) 47 48 def meta_key(self): 49 """Extra metadata that doesn't form part of the test identity, but for 50 which changes mean regenerating the manifest (e.g. the test timeout.""" 51 return () 52 53 def __eq__(self, other): 54 if not hasattr(other, "key"): 55 return False 56 return self.key() == other.key() 57 58 def __hash__(self): 59 return hash(self.key() + self.meta_key()) 60 61 def __repr__(self): 62 return "<%s.%s id=%s, path=%s>" % (self.__module__, self.__class__.__name__, self.id, self.path) 63 64 def to_json(self): 65 return [{}] 66 67 @classmethod 68 def from_json(cls, manifest, tests_root, path, obj, source_files=None): 69 source_file = get_source_file(source_files, tests_root, manifest, path) 70 return cls(source_file, 71 manifest=manifest) 72 73 74class URLManifestItem(ManifestItem): 75 def __init__(self, source_file, url, url_base="/", manifest=None): 76 ManifestItem.__init__(self, source_file, manifest=manifest) 77 self._url = url 78 self.url_base = url_base 79 80 @property 81 def id(self): 82 return self.url 83 84 @property 85 def url(self): 86 return urljoin(self.url_base, self._url) 87 88 def to_json(self): 89 rv = [self._url, {}] 90 return rv 91 92 @classmethod 93 def from_json(cls, manifest, tests_root, path, obj, source_files=None): 94 source_file = get_source_file(source_files, tests_root, manifest, path) 95 url, extras = obj 96 return cls(source_file, 97 url, 98 url_base=manifest.url_base, 99 manifest=manifest) 100 101 102class TestharnessTest(URLManifestItem): 103 item_type = "testharness" 104 105 def __init__(self, source_file, url, url_base="/", timeout=None, testdriver=False, manifest=None): 106 URLManifestItem.__init__(self, source_file, url, url_base=url_base, manifest=manifest) 107 self.timeout = timeout 108 self.testdriver = testdriver 109 110 def meta_key(self): 111 return (self.timeout, self.testdriver) 112 113 def to_json(self): 114 rv = URLManifestItem.to_json(self) 115 if self.timeout is not None: 116 rv[-1]["timeout"] = self.timeout 117 if self.testdriver: 118 rv[-1]["testdriver"] = self.testdriver 119 return rv 120 121 @classmethod 122 def from_json(cls, manifest, tests_root, path, obj, source_files=None): 123 source_file = get_source_file(source_files, tests_root, manifest, path) 124 125 url, extras = obj 126 return cls(source_file, 127 url, 128 url_base=manifest.url_base, 129 timeout=extras.get("timeout"), 130 testdriver=bool(extras.get("testdriver")), 131 manifest=manifest) 132 133 134class RefTestNode(URLManifestItem): 135 item_type = "reftest_node" 136 137 def __init__(self, source_file, url, references, url_base="/", timeout=None, 138 viewport_size=None, dpi=None, manifest=None): 139 URLManifestItem.__init__(self, source_file, url, url_base=url_base, manifest=manifest) 140 for _, ref_type in references: 141 if ref_type not in ["==", "!="]: 142 raise ValueError("Unrecognised ref_type %s" % ref_type) 143 self.references = tuple(references) 144 self.timeout = timeout 145 self.viewport_size = viewport_size 146 self.dpi = dpi 147 148 def meta_key(self): 149 return (self.timeout, self.viewport_size, self.dpi) 150 151 def to_json(self): 152 rv = [self.url, self.references, {}] 153 extras = rv[-1] 154 if self.timeout is not None: 155 extras["timeout"] = self.timeout 156 if self.viewport_size is not None: 157 extras["viewport_size"] = self.viewport_size 158 if self.dpi is not None: 159 extras["dpi"] = self.dpi 160 return rv 161 162 @classmethod 163 def from_json(cls, manifest, tests_root, path, obj, source_files=None): 164 source_file = get_source_file(source_files, tests_root, manifest, path) 165 url, references, extras = obj 166 return cls(source_file, 167 url, 168 references, 169 url_base=manifest.url_base, 170 timeout=extras.get("timeout"), 171 viewport_size=extras.get("viewport_size"), 172 dpi=extras.get("dpi"), 173 manifest=manifest) 174 175 def to_RefTest(self): 176 if type(self) == RefTest: 177 return self 178 rv = RefTest.__new__(RefTest) 179 rv.__dict__.update(self.__dict__) 180 return rv 181 182 def to_RefTestNode(self): 183 if type(self) == RefTestNode: 184 return self 185 rv = RefTestNode.__new__(RefTestNode) 186 rv.__dict__.update(self.__dict__) 187 return rv 188 189 190class RefTest(RefTestNode): 191 item_type = "reftest" 192 193 194class ManualTest(URLManifestItem): 195 item_type = "manual" 196 197 198class ConformanceCheckerTest(URLManifestItem): 199 item_type = "conformancechecker" 200 201 202class VisualTest(URLManifestItem): 203 item_type = "visual" 204 205 206class Stub(URLManifestItem): 207 item_type = "stub" 208 209 210class WebdriverSpecTest(URLManifestItem): 211 item_type = "wdspec" 212 213 def __init__(self, source_file, url, url_base="/", timeout=None, manifest=None): 214 URLManifestItem.__init__(self, source_file, url, url_base=url_base, manifest=manifest) 215 self.timeout = timeout 216 217 def to_json(self): 218 rv = URLManifestItem.to_json(self) 219 if self.timeout is not None: 220 rv[-1]["timeout"] = self.timeout 221 return rv 222 223 @classmethod 224 def from_json(cls, manifest, tests_root, path, obj, source_files=None): 225 source_file = get_source_file(source_files, tests_root, manifest, path) 226 227 url, extras = obj 228 return cls(source_file, 229 url, 230 url_base=manifest.url_base, 231 timeout=extras.get("timeout"), 232 manifest=manifest) 233 234 235class SupportFile(ManifestItem): 236 item_type = "support" 237 238 @property 239 def id(self): 240 return self.source_file.rel_path 241