import os from six.moves.urllib.parse import urljoin from abc import ABCMeta, abstractmethod, abstractproperty def get_source_file(source_files, tests_root, manifest, path): def make_new(): from .sourcefile import SourceFile return SourceFile(tests_root, path, manifest.url_base) if source_files is None: return make_new() if path not in source_files: source_files[path] = make_new() return source_files[path] class ManifestItem(object): __metaclass__ = ABCMeta item_type = None def __init__(self, source_file, manifest=None): self.manifest = manifest self.source_file = source_file @abstractproperty def id(self): """The test's id (usually its url)""" pass @property def path(self): """The test path relative to the test_root""" return self.source_file.rel_path @property def https(self): return "https" in self.source_file.meta_flags def key(self): """A unique identifier for the test""" return (self.item_type, self.id) def meta_key(self): """Extra metadata that doesn't form part of the test identity, but for which changes mean regenerating the manifest (e.g. the test timeout.""" return () def __eq__(self, other): if not hasattr(other, "key"): return False return self.key() == other.key() def __hash__(self): return hash(self.key() + self.meta_key()) def __repr__(self): return "<%s.%s id=%s, path=%s>" % (self.__module__, self.__class__.__name__, self.id, self.path) def to_json(self): return [{}] @classmethod def from_json(cls, manifest, tests_root, path, obj, source_files=None): source_file = get_source_file(source_files, tests_root, manifest, path) return cls(source_file, manifest=manifest) class URLManifestItem(ManifestItem): def __init__(self, source_file, url, url_base="/", manifest=None): ManifestItem.__init__(self, source_file, manifest=manifest) self._url = url self.url_base = url_base @property def id(self): return self.url @property def url(self): return urljoin(self.url_base, self._url) def to_json(self): rv = [self._url, {}] return rv @classmethod def from_json(cls, manifest, tests_root, path, obj, source_files=None): source_file = get_source_file(source_files, tests_root, manifest, path) url, extras = obj return cls(source_file, url, url_base=manifest.url_base, manifest=manifest) class TestharnessTest(URLManifestItem): item_type = "testharness" def __init__(self, source_file, url, url_base="/", timeout=None, manifest=None): URLManifestItem.__init__(self, source_file, url, url_base=url_base, manifest=manifest) self.timeout = timeout def meta_key(self): return (self.timeout,) def to_json(self): rv = URLManifestItem.to_json(self) if self.timeout is not None: rv[-1]["timeout"] = self.timeout return rv @classmethod def from_json(cls, manifest, tests_root, path, obj, source_files=None): source_file = get_source_file(source_files, tests_root, manifest, path) url, extras = obj return cls(source_file, url, url_base=manifest.url_base, timeout=extras.get("timeout"), manifest=manifest) class RefTestNode(URLManifestItem): item_type = "reftest_node" def __init__(self, source_file, url, references, url_base="/", timeout=None, viewport_size=None, dpi=None, manifest=None): URLManifestItem.__init__(self, source_file, url, url_base=url_base, manifest=manifest) for _, ref_type in references: if ref_type not in ["==", "!="]: raise ValueError("Unrecognised ref_type %s" % ref_type) self.references = tuple(references) self.timeout = timeout self.viewport_size = viewport_size self.dpi = dpi def meta_key(self): return (self.timeout, self.viewport_size, self.dpi) def to_json(self): rv = [self.url, self.references, {}] extras = rv[-1] if self.timeout is not None: extras["timeout"] = self.timeout if self.viewport_size is not None: extras["viewport_size"] = self.viewport_size if self.dpi is not None: extras["dpi"] = self.dpi return rv @classmethod def from_json(cls, manifest, tests_root, path, obj, source_files=None): source_file = get_source_file(source_files, tests_root, manifest, path) url, references, extras = obj return cls(source_file, url, references, url_base=manifest.url_base, timeout=extras.get("timeout"), viewport_size=extras.get("viewport_size"), dpi=extras.get("dpi"), manifest=manifest) def to_RefTest(self): if type(self) == RefTest: return self rv = RefTest.__new__(RefTest) rv.__dict__.update(self.__dict__) return rv def to_RefTestNode(self): if type(self) == RefTestNode: return self rv = RefTestNode.__new__(RefTestNode) rv.__dict__.update(self.__dict__) return rv class RefTest(RefTestNode): item_type = "reftest" class ManualTest(URLManifestItem): item_type = "manual" class ConformanceCheckerTest(URLManifestItem): item_type = "conformancechecker" class VisualTest(URLManifestItem): item_type = "visual" class Stub(URLManifestItem): item_type = "stub" class WebdriverSpecTest(URLManifestItem): item_type = "wdspec" def __init__(self, source_file, url, url_base="/", timeout=None, manifest=None): URLManifestItem.__init__(self, source_file, url, url_base=url_base, manifest=manifest) self.timeout = timeout class SupportFile(ManifestItem): item_type = "support" @property def id(self): return self.source_file.rel_path