Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / tests / manifest.py
1 # Library for JSTest manifests.
2 #
3 # This includes classes for representing and parsing JS manifests.
4
5 import os, re, sys
6 from subprocess import *
7
8 from tests import TestCase
9
10 class XULInfo:
11     def __init__(self, abi, os, isdebug):
12         self.abi = abi
13         self.os = os
14         self.isdebug = isdebug
15
16     def as_js(self):
17         """Return JS that when executed sets up variables so that JS expression
18         predicates on XUL build info evaluate properly."""
19
20         return 'var xulRuntime = { OS: "%s", XPCOMABI: "%s", shell: true }; var isDebugBuild=%s;' % (
21             self.os,
22             self.abi,
23             str(self.isdebug).lower())
24
25     @classmethod
26     def create(cls, jsdir):
27         """Create a XULInfo based on the current platform's characteristics."""
28
29         # Our strategy is to find the autoconf.mk generated for the build and
30         # read the values from there.
31         
32         # Find config/autoconf.mk.
33         dir = jsdir
34         while True:
35             path = os.path.join(dir, 'config/autoconf.mk')
36             if os.path.isfile(path):
37                 break
38             if os.path.dirname(dir) == dir:
39                 print "Can't find config/autoconf.mk on a directory containing the JS shell (searched from %s)"%jsdir
40                 sys.exit(1)
41             dir = os.path.dirname(dir)
42
43         # Read the values.
44         val_re = re.compile(r'(TARGET_XPCOM_ABI|OS_TARGET|MOZ_DEBUG)\s*=\s*(.*)')
45         kw = {}
46         for line in open(path):
47             m = val_re.match(line)
48             if m:
49                 key, val = m.groups()
50                 val = val.rstrip()
51                 if key == 'TARGET_XPCOM_ABI':
52                     kw['abi'] = val
53                 if key == 'OS_TARGET':
54                     kw['os'] = val
55                 if key == 'MOZ_DEBUG':
56                     kw['isdebug'] = (val == '1')
57         return cls(**kw)
58
59 class XULInfoTester:
60     def __init__(self, xulinfo, js_bin):
61         self.js_prolog = xulinfo.as_js()
62         self.js_bin = js_bin
63         # Maps JS expr to evaluation result.
64         self.cache = {}
65
66     def test(self, cond):
67         """Test a XUL predicate condition against this local info."""
68         ans = self.cache.get(cond, None)
69         if ans is None:
70             cmd = [ self.js_bin, '-e', self.js_prolog, '-e', 'print(!!(%s))'%cond ]
71             p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
72             out, err = p.communicate()
73             if out in ('true\n', 'true\r\n'):
74                 ans = True
75             elif out in ('false\n', 'false\r\n'):
76                 ans = False
77             else:
78                 raise Exception("Failed to test XUL condition '%s'"%cond)
79             self.cache[cond] = ans
80         return ans
81
82 class NullXULInfoTester:
83     """Can be used to parse manifests without a JS shell."""
84     def test(self, cond):
85         return False
86
87 def parse(filename, xul_tester, reldir = ''):
88     ans = []
89     comment_re = re.compile(r'#.*')
90     dir = os.path.dirname(filename)
91
92     try:
93         f = open(filename)
94     except IOError:
95         print "warning: include file not found: '%s'"%filename
96         return ans
97
98     for line in f:
99         sline = comment_re.sub('', line)
100         parts = sline.split()
101         if len(parts) == 0:
102             # line is empty or just a comment, skip
103             pass
104         elif parts[0] == 'include':
105             include_file = parts[1]
106             include_reldir = os.path.join(reldir, os.path.dirname(include_file))
107             ans += parse(os.path.join(dir, include_file), xul_tester, include_reldir)
108         elif parts[0] == 'url-prefix':
109             # Doesn't apply to shell tests
110             pass
111         else:
112             script = None
113             enable = True
114             expect = True
115             random = False
116             slow = False
117
118             pos = 0
119             while pos < len(parts):
120                 if parts[pos] == 'fails':
121                     expect = False
122                     pos += 1
123                 elif parts[pos] == 'skip':
124                     expect = enable = False
125                     pos += 1
126                 elif parts[pos] == 'random':
127                     random = True
128                     pos += 1
129                 elif parts[pos].startswith('fails-if'):
130                     cond = parts[pos][len('fails-if('):-1]
131                     if xul_tester.test(cond):
132                         expect = False
133                     pos += 1
134                 elif parts[pos].startswith('asserts-if'):
135                     # This directive means we may flunk some number of
136                     # NS_ASSERTIONs in the browser. For the shell, ignore it.
137                     pos += 1
138                 elif parts[pos].startswith('skip-if'):
139                     cond = parts[pos][len('skip-if('):-1]
140                     if xul_tester.test(cond):
141                         expect = enable = False
142                     pos += 1
143                 elif parts[pos].startswith('random-if'):
144                     cond = parts[pos][len('random-if('):-1]
145                     if xul_tester.test(cond):
146                         random = True
147                     pos += 1
148                 elif parts[pos] == 'script':
149                     script = parts[pos+1]
150                     pos += 2
151                 elif parts[pos] == 'slow':
152                     slow = True
153                     pos += 1
154                 elif parts[pos] == 'silentfail':
155                     # silentfails use tons of memory, and Darwin doesn't support ulimit.
156                     if xul_tester.test("xulRuntime.OS == 'Darwin'"):
157                         expect = enable = False
158                     pos += 1
159                 else:
160                     print 'warning: invalid manifest line element "%s"'%parts[pos]
161                     pos += 1
162
163             assert script is not None
164             ans.append(TestCase(os.path.join(reldir, script), 
165                                 enable, expect, random, slow))
166     return ans