f68164ef2f1ebfcfa34a1dc90fb41b5e387343cb
[WebKit-https.git] / Tools / Scripts / webkitpy / layout_tests / port / factory.py
1 #!/usr/bin/env python
2 # Copyright (C) 2010 Google Inc. All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
6 # met:
7 #
8 #     * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 #     * Redistributions in binary form must reproduce the above
11 # copyright notice, this list of conditions and the following disclaimer
12 # in the documentation and/or other materials provided with the
13 # distribution.
14 #     * Neither the name of Google Inc. nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 """Factory method to retrieve the appropriate port implementation."""
31
32 import optparse
33 import re
34
35 from webkitpy.layout_tests.port import builders
36
37
38 def platform_options(**help_strings):
39     return [
40         optparse.make_option('--platform', action='store',
41             help=help_strings.get('platform', 'Platform/Port being tested (e.g., "mac-lion")')),
42         optparse.make_option('--chromium', action='store_const', const='chromium', dest='platform',
43             help='Alias for --platform=chromium'),
44         optparse.make_option('--chromium-android', action='store_const', const='chromium-android', dest='platform',
45             help='Alias for --platform=chromium-android'),
46         optparse.make_option('--efl', action='store_const', const='efl', dest="platform",
47             help='Alias for --platform=efl'),
48         optparse.make_option('--gtk', action='store_const', const='gtk', dest="platform",
49             help='Alias for --platform=gtk'),
50         optparse.make_option('--qt', action='store_const', const='qt', dest="platform",
51             help='Alias for --platform=qt'),
52         ]
53
54
55 def configuration_options():
56     return [
57         optparse.make_option("-t", "--target", dest="configuration", help="(DEPRECATED)"),
58         # FIXME: --help should display which configuration is default.
59         optparse.make_option('--debug', action='store_const', const='Debug', dest="configuration",
60             help='Set the configuration to Debug'),
61         optparse.make_option('--release', action='store_const', const='Release', dest="configuration",
62             help='Set the configuration to Release'),
63         optparse.make_option('--32-bit', action='store_const', const='x86', default=None, dest="architecture",
64             help='use 32-bit binaries by default (x86 instead of x86_64)'),
65         ]
66
67
68
69 def _builder_options(builder_name):
70     configuration = "Debug" if re.search(r"[d|D](ebu|b)g", builder_name) else "Release"
71     is_webkit2 = builder_name.find("WK2") != -1
72     builder_name = builder_name
73     return optparse.Values({'builder_name': builder_name, 'configuration': configuration, 'webkit_test_runner': is_webkit2})
74
75
76 class PortFactory(object):
77     PORT_CLASSES = (
78         'chromium_android.ChromiumAndroidPort',
79         'chromium_linux.ChromiumLinuxPort',
80         'chromium_mac.ChromiumMacPort',
81         'chromium_win.ChromiumWinPort',
82         'efl.EflPort',
83         'gtk.GtkPort',
84         'mac.MacPort',
85         'mock_drt.MockDRTPort',
86         'qt.QtPort',
87         'test.TestPort',
88         'win.WinPort',
89     )
90
91     def __init__(self, host):
92         self._host = host
93
94     def _default_port(self, options):
95         platform = self._host.platform
96         if platform.is_linux() or platform.is_freebsd():
97             return 'chromium-linux'
98         elif platform.is_mac():
99             return 'mac'
100         elif platform.is_win():
101             return 'win'
102         raise NotImplementedError('unknown platform: %s' % platform)
103
104     def get(self, port_name=None, options=None, **kwargs):
105         """Returns an object implementing the Port interface. If
106         port_name is None, this routine attempts to guess at the most
107         appropriate port on this platform."""
108         port_name = port_name or self._default_port(options)
109
110         # FIXME(dpranke): We special-case '--platform chromium' so that it can co-exist
111         # with '--platform chromium-mac' and '--platform chromium-linux' properly (we
112         # can't look at the port_name prefix in this case).
113         if port_name == 'chromium':
114             port_name = 'chromium-' + self._host.platform.os_name
115
116         for port_class in self.PORT_CLASSES:
117             module_name, class_name = port_class.rsplit('.', 1)
118             module = __import__(module_name, globals(), locals(), [], -1)
119             cls = module.__dict__[class_name]
120             if port_name.startswith(cls.port_name):
121                 port_name = cls.determine_full_port_name(self._host, options, port_name)
122                 return cls(self._host, port_name, options=options, **kwargs)
123         raise NotImplementedError('unsupported platform: "%s"' % port_name)
124
125     def all_port_names(self):
126         """Return a list of all valid, fully-specified, "real" port names.
127
128         This is the list of directories that are used as actual baseline_paths()
129         by real ports. This does not include any "fake" names like "test"
130         or "mock-mac", and it does not include any directories that are not ."""
131         # FIXME: There's probably a better way to generate this list ...
132         return builders.all_port_names()
133
134     def get_from_builder_name(self, builder_name):
135         port_name = builders.port_name_for_builder_name(builder_name)
136         assert(port_name)  # Need to update port_name_for_builder_name
137         port = self.get(port_name, _builder_options(builder_name))
138         assert(port)  # Need to update port_name_for_builder_name
139         return port