1 | # ***** BEGIN LICENSE BLOCK *****
|
---|
2 | # Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
---|
3 | #
|
---|
4 | # The contents of this file are subject to the Mozilla Public License Version
|
---|
5 | # 1.1 (the "License"); you may not use this file except in compliance with
|
---|
6 | # the License. You may obtain a copy of the License at
|
---|
7 | # http://www.mozilla.org/MPL/
|
---|
8 | #
|
---|
9 | # Software distributed under the License is distributed on an "AS IS" basis,
|
---|
10 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
---|
11 | # for the specific language governing rights and limitations under the
|
---|
12 | # License.
|
---|
13 | #
|
---|
14 | # The Original Code is the Python XPCOM language bindings.
|
---|
15 | #
|
---|
16 | # The Initial Developer of the Original Code is
|
---|
17 | # ActiveState Tool Corp.
|
---|
18 | # Portions created by the Initial Developer are Copyright (C) 2000, 2001
|
---|
19 | # the Initial Developer. All Rights Reserved.
|
---|
20 | #
|
---|
21 | # Contributor(s):
|
---|
22 | # Mark Hammond <[email protected]> (original author)
|
---|
23 | #
|
---|
24 | # Alternatively, the contents of this file may be used under the terms of
|
---|
25 | # either the GNU General Public License Version 2 or later (the "GPL"), or
|
---|
26 | # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
---|
27 | # in which case the provisions of the GPL or the LGPL are applicable instead
|
---|
28 | # of those above. If you wish to allow use of your version of this file only
|
---|
29 | # under the terms of either the GPL or the LGPL, and not to allow others to
|
---|
30 | # use your version of this file under the terms of the MPL, indicate your
|
---|
31 | # decision by deleting the provisions above and replace them with the notice
|
---|
32 | # and other provisions required by the GPL or the LGPL. If you do not delete
|
---|
33 | # the provisions above, a recipient may use your version of this file under
|
---|
34 | # the terms of any one of the MPL, the GPL or the LGPL.
|
---|
35 | #
|
---|
36 | # ***** END LICENSE BLOCK *****
|
---|
37 |
|
---|
38 | import sys, os, time
|
---|
39 | import xpcom.components
|
---|
40 | import xpcom._xpcom
|
---|
41 | import xpcom.nsError
|
---|
42 |
|
---|
43 | MakeVariant = xpcom._xpcom.MakeVariant
|
---|
44 |
|
---|
45 | try:
|
---|
46 | import gc
|
---|
47 | except ImportError:
|
---|
48 | gc = None
|
---|
49 |
|
---|
50 | num_errors = 0
|
---|
51 |
|
---|
52 | component_iid = xpcom.components.ID("{7EE4BDC6-CB53-42c1-A9E4-616B8E012ABA}")
|
---|
53 | new_iid = xpcom.components.ID("{2AF747D3-ECBC-457b-9AF9-5C5D80EDC360}")
|
---|
54 |
|
---|
55 | contractid = "Python.TestComponent"
|
---|
56 |
|
---|
57 | really_big_string = "This is really repetitive!" * 10000
|
---|
58 | really_big_wstring = u"This is really repetitive!" * 10000
|
---|
59 | extended_unicode_string = u"The Euro Symbol is '\u20ac'"
|
---|
60 |
|
---|
61 | # Exception raised when a -ve integer is converted to an unsigned C integer
|
---|
62 | # (via an extension module). This changed in Python 2.2
|
---|
63 | if sys.hexversion > 0x02010000:
|
---|
64 | UnsignedMismatchException = TypeError
|
---|
65 | else:
|
---|
66 | UnsignedMismatchException = OverflowError
|
---|
67 |
|
---|
68 | def print_error(error):
|
---|
69 | print error
|
---|
70 | global num_errors
|
---|
71 | num_errors = num_errors + 1
|
---|
72 |
|
---|
73 | def _test_value(what, got, expecting):
|
---|
74 | ok = got == expecting
|
---|
75 | if type(got)==type(expecting)==type(0.0):
|
---|
76 | ok = abs(got-expecting) < 0.001
|
---|
77 | if not ok:
|
---|
78 | print_error("*** Error %s - got '%r', but expecting '%r'" % (what, got, expecting))
|
---|
79 |
|
---|
80 | def test_attribute(ob, attr_name, expected_init, new_value, new_value_really = None):
|
---|
81 | if xpcom.verbose:
|
---|
82 | print "Testing attribute %s" % (attr_name,)
|
---|
83 | if new_value_really is None:
|
---|
84 | new_value_really = new_value # Handy for eg bools - set a BOOL to 2, you still get back 1!
|
---|
85 |
|
---|
86 | _test_value( "getting initial attribute value (%s)" % (attr_name,), getattr(ob, attr_name), expected_init)
|
---|
87 | setattr(ob, attr_name, new_value)
|
---|
88 | _test_value( "getting new attribute value (%s)" % (attr_name,), getattr(ob, attr_name), new_value_really)
|
---|
89 | # And set it back to the expected init.
|
---|
90 | setattr(ob, attr_name, expected_init)
|
---|
91 | _test_value( "getting back initial attribute value after change (%s)" % (attr_name,), getattr(ob, attr_name), expected_init)
|
---|
92 |
|
---|
93 | def test_string_attribute(ob, attr_name, expected_init, is_dumb_sz = False, ascii_only = False):
|
---|
94 | test_attribute(ob, attr_name, expected_init, "normal value")
|
---|
95 | val = "a null >\0<"
|
---|
96 | if is_dumb_sz:
|
---|
97 | expected = "a null >" # dumb strings are \0 terminated.
|
---|
98 | else:
|
---|
99 | expected = val
|
---|
100 | test_attribute(ob, attr_name, expected_init, val, expected)
|
---|
101 | test_attribute(ob, attr_name, expected_init, "")
|
---|
102 | test_attribute(ob, attr_name, expected_init, really_big_string)
|
---|
103 | test_attribute(ob, attr_name, expected_init, u"normal unicode value")
|
---|
104 | val = u"a null >\0<"
|
---|
105 | if is_dumb_sz:
|
---|
106 | expected = "a null >" # dumb strings are \0 terminated.
|
---|
107 | else:
|
---|
108 | expected = val
|
---|
109 | test_attribute(ob, attr_name, expected_init, val, expected)
|
---|
110 | test_attribute(ob, attr_name, expected_init, u"")
|
---|
111 | test_attribute(ob, attr_name, expected_init, really_big_wstring)
|
---|
112 | if not ascii_only:
|
---|
113 | test_attribute(ob, attr_name, expected_init, extended_unicode_string)
|
---|
114 |
|
---|
115 | def test_attribute_failure(ob, attr_name, new_value, expected_exception):
|
---|
116 | try:
|
---|
117 | setattr(ob, attr_name, new_value)
|
---|
118 | print_error("*** Setting attribute '%s' to '%r' didnt yield an exception!" % (attr_name, new_value) )
|
---|
119 | except:
|
---|
120 | exc_typ = sys.exc_info()[0]
|
---|
121 | exc_val = sys.exc_info()[1]
|
---|
122 | ok = issubclass(exc_typ, expected_exception)
|
---|
123 | if not ok:
|
---|
124 | print_error("*** Wrong exception setting '%s' to '%r'- got '%s: %s', expected '%s'" % (attr_name, new_value, exc_typ, exc_val, expected_exception))
|
---|
125 |
|
---|
126 |
|
---|
127 | def test_method(method, args, expected_results):
|
---|
128 | if xpcom.verbose:
|
---|
129 | print "Testing %s%s" % (method.__name__, `args`)
|
---|
130 | ret = method(*args)
|
---|
131 | if ret != expected_results:
|
---|
132 | print_error("calling method %s - expected %r, but got %r" % (method.__name__, expected_results, ret))
|
---|
133 |
|
---|
134 | def test_int_method(meth):
|
---|
135 | test_method(meth, (0,0), (0,0,0))
|
---|
136 | test_method(meth, (1,1), (2,0,1))
|
---|
137 | test_method(meth, (5,2), (7,3,10))
|
---|
138 | # test_method(meth, (2,5), (7,-3,10))
|
---|
139 |
|
---|
140 | def test_constant(ob, cname, val):
|
---|
141 | v = getattr(ob, cname)
|
---|
142 | if v != val:
|
---|
143 | print_error("Bad value for constant '%s' - got '%r'" % (cname, v))
|
---|
144 | try:
|
---|
145 | setattr(ob, cname, 0)
|
---|
146 | print_error("The object allowed us to set the constant '%s'" % (cname,))
|
---|
147 | except AttributeError:
|
---|
148 | pass
|
---|
149 |
|
---|
150 | def test_base_interface(c):
|
---|
151 | test_attribute(c, "boolean_value", 1, 0)
|
---|
152 | test_attribute(c, "boolean_value", 1, -1, 1) # Set a bool to anything, you should always get back 0 or 1
|
---|
153 | test_attribute(c, "boolean_value", 1, 4, 1) # Set a bool to anything, you should always get back 0 or 1
|
---|
154 | test_attribute(c, "boolean_value", 1, "1", 1) # This works by virtual of PyNumber_Int - not sure I agree, but...
|
---|
155 | test_attribute_failure(c, "boolean_value", "boo", ValueError)
|
---|
156 | test_attribute_failure(c, "boolean_value", test_base_interface, TypeError)
|
---|
157 |
|
---|
158 | test_attribute(c, "octet_value", 2, 5)
|
---|
159 | test_attribute(c, "octet_value", 2, 0)
|
---|
160 | test_attribute(c, "octet_value", 2, 128) # octet is unsigned 8 bit
|
---|
161 | test_attribute(c, "octet_value", 2, 255) # octet is unsigned 8 bit
|
---|
162 | test_attribute(c, "octet_value", 2, -1, 255) # octet is unsigned 8 bit
|
---|
163 | test_attribute_failure(c, "octet_value", "boo", ValueError)
|
---|
164 |
|
---|
165 | test_attribute(c, "short_value", 3, 10)
|
---|
166 | test_attribute(c, "short_value", 3, -1) # 16 bit signed
|
---|
167 | test_attribute(c, "short_value", 3, 0xFFFF, -1) # 16 bit signed
|
---|
168 | test_attribute(c, "short_value", 3, 0L)
|
---|
169 | test_attribute(c, "short_value", 3, 1L)
|
---|
170 | test_attribute(c, "short_value", 3, -1L)
|
---|
171 | test_attribute(c, "short_value", 3, 0xFFFFL, -1)
|
---|
172 | test_attribute_failure(c, "short_value", "boo", ValueError)
|
---|
173 |
|
---|
174 | test_attribute(c, "ushort_value", 4, 5)
|
---|
175 | test_attribute(c, "ushort_value", 4, 0)
|
---|
176 | test_attribute(c, "ushort_value", 4, -1, 0xFFFF) # 16 bit signed
|
---|
177 | test_attribute(c, "ushort_value", 4, 0xFFFF) # 16 bit signed
|
---|
178 | test_attribute(c, "ushort_value", 4, 0L)
|
---|
179 | test_attribute(c, "ushort_value", 4, 1L)
|
---|
180 | test_attribute(c, "ushort_value", 4, -1L, 0xFFFF)
|
---|
181 | test_attribute_failure(c, "ushort_value", "boo", ValueError)
|
---|
182 |
|
---|
183 | test_attribute(c, "long_value", 5, 7)
|
---|
184 | test_attribute(c, "long_value", 5, 0)
|
---|
185 | test_attribute(c, "long_value", 5, -1, -1) # 32 bit signed.
|
---|
186 | test_attribute(c, "long_value", 5, -1) # 32 bit signed.
|
---|
187 | test_attribute(c, "long_value", 5, 0L)
|
---|
188 | test_attribute(c, "long_value", 5, 1L)
|
---|
189 | test_attribute(c, "long_value", 5, -1L)
|
---|
190 | test_attribute_failure(c, "long_value", 0xFFFFL * 0xFFFF, OverflowError) # long int too long to convert
|
---|
191 | test_attribute_failure(c, "long_value", "boo", ValueError)
|
---|
192 |
|
---|
193 | test_attribute(c, "ulong_value", 6, 7)
|
---|
194 | test_attribute(c, "ulong_value", 6, 0)
|
---|
195 | test_attribute(c, "ulong_value", 6, -1) # 32 bit signed.
|
---|
196 | test_attribute_failure(c, "ulong_value", "boo", ValueError)
|
---|
197 |
|
---|
198 | test_attribute(c, "long_long_value", 7, 8)
|
---|
199 | test_attribute(c, "long_long_value", 7, 0)
|
---|
200 | test_attribute(c, "long_long_value", 7, -1)
|
---|
201 | test_attribute(c, "long_long_value", 7, 0xFFFF)
|
---|
202 | test_attribute(c, "long_long_value", 7, 0xFFFFL * 2)
|
---|
203 | test_attribute_failure(c, "long_long_value", 0xFFFFL * 0xFFFF * 0xFFFF * 0xFFFF, OverflowError) # long int too long to convert
|
---|
204 | test_attribute_failure(c, "long_long_value", "boo", ValueError)
|
---|
205 |
|
---|
206 | test_attribute(c, "ulong_long_value", 8, 9)
|
---|
207 | test_attribute(c, "ulong_long_value", 8, 0)
|
---|
208 | test_attribute_failure(c, "ulong_long_value", "boo", ValueError)
|
---|
209 | test_attribute_failure(c, "ulong_long_value", -1, UnsignedMismatchException) # can't convert negative value to unsigned long)
|
---|
210 |
|
---|
211 | test_attribute(c, "float_value", 9.0, 10.2)
|
---|
212 | test_attribute(c, "float_value", 9.0, 0)
|
---|
213 | test_attribute(c, "float_value", 9.0, -1)
|
---|
214 | test_attribute(c, "float_value", 9.0, 1L)
|
---|
215 | test_attribute_failure(c, "float_value", "boo", ValueError)
|
---|
216 |
|
---|
217 | test_attribute(c, "double_value", 10.0, 9.0)
|
---|
218 | test_attribute(c, "double_value", 10.0, 0)
|
---|
219 | test_attribute(c, "double_value", 10.0, -1)
|
---|
220 | test_attribute(c, "double_value", 10.0, 1L)
|
---|
221 | test_attribute_failure(c, "double_value", "boo", ValueError)
|
---|
222 |
|
---|
223 | test_attribute(c, "char_value", "a", "b")
|
---|
224 | test_attribute(c, "char_value", "a", "\0")
|
---|
225 | test_attribute_failure(c, "char_value", "xy", ValueError)
|
---|
226 | test_attribute(c, "char_value", "a", u"c")
|
---|
227 | test_attribute(c, "char_value", "a", u"\0")
|
---|
228 | test_attribute_failure(c, "char_value", u"xy", ValueError)
|
---|
229 |
|
---|
230 | test_attribute(c, "wchar_value", "b", "a")
|
---|
231 | test_attribute(c, "wchar_value", "b", "\0")
|
---|
232 | test_attribute_failure(c, "wchar_value", "hi", ValueError)
|
---|
233 | test_attribute(c, "wchar_value", "b", u"a")
|
---|
234 | test_attribute(c, "wchar_value", "b", u"\0")
|
---|
235 | test_attribute_failure(c, "wchar_value", u"hi", ValueError)
|
---|
236 |
|
---|
237 | test_string_attribute(c, "string_value", "cee", is_dumb_sz = True, ascii_only = True)
|
---|
238 | test_string_attribute(c, "wstring_value", "dee", is_dumb_sz = True)
|
---|
239 | test_string_attribute(c, "astring_value", "astring")
|
---|
240 | test_string_attribute(c, "acstring_value", "acstring", ascii_only = True)
|
---|
241 |
|
---|
242 | test_string_attribute(c, "utf8string_value", "utf8string")
|
---|
243 | # Test a string already encoded gets through correctly.
|
---|
244 | test_attribute(c, "utf8string_value", "utf8string", extended_unicode_string.encode("utf8"), extended_unicode_string)
|
---|
245 |
|
---|
246 | # This will fail internal string representation :( Test we don't crash
|
---|
247 | try:
|
---|
248 | c.wstring_value = "a big char >" + chr(129) + "<"
|
---|
249 | print_error("strings with chars > 128 appear to have stopped failing?")
|
---|
250 | except UnicodeError:
|
---|
251 | pass
|
---|
252 |
|
---|
253 | test_attribute(c, "iid_value", component_iid, new_iid)
|
---|
254 | test_attribute(c, "iid_value", component_iid, str(new_iid), new_iid)
|
---|
255 | test_attribute(c, "iid_value", component_iid, xpcom._xpcom.IID(new_iid))
|
---|
256 |
|
---|
257 | test_attribute_failure(c, "no_attribute", "boo", AttributeError)
|
---|
258 |
|
---|
259 | test_attribute(c, "interface_value", None, c)
|
---|
260 | test_attribute_failure(c, "interface_value", 2, TypeError)
|
---|
261 |
|
---|
262 | test_attribute(c, "isupports_value", None, c)
|
---|
263 |
|
---|
264 | # The methods
|
---|
265 | test_method(c.do_boolean, (0,1), (1,0,1))
|
---|
266 | test_method(c.do_boolean, (1,0), (1,0,1))
|
---|
267 | test_method(c.do_boolean, (1,1), (0,1,0))
|
---|
268 |
|
---|
269 | test_int_method(c.do_octet)
|
---|
270 | test_int_method(c.do_short)
|
---|
271 |
|
---|
272 | test_int_method(c.do_unsigned_short)
|
---|
273 | test_int_method(c.do_long)
|
---|
274 | test_int_method(c.do_unsigned_long)
|
---|
275 | test_int_method(c.do_long_long)
|
---|
276 | test_int_method(c.do_unsigned_long)
|
---|
277 | test_int_method(c.do_float)
|
---|
278 | test_int_method(c.do_double)
|
---|
279 |
|
---|
280 | test_method(c.do_char, ("A", " "), (chr(ord("A")+ord(" ")), " ","A") )
|
---|
281 | test_method(c.do_char, ("A", "\0"), ("A", "\0","A") )
|
---|
282 | test_method(c.do_wchar, ("A", " "), (chr(ord("A")+ord(" ")), " ","A") )
|
---|
283 | test_method(c.do_wchar, ("A", "\0"), ("A", "\0","A") )
|
---|
284 |
|
---|
285 | test_method(c.do_string, ("Hello from ", "Python"), ("Hello from Python", "Hello from ", "Python") )
|
---|
286 | test_method(c.do_string, (u"Hello from ", u"Python"), ("Hello from Python", "Hello from ", "Python") )
|
---|
287 | test_method(c.do_string, (None, u"Python"), ("Python", None, "Python") )
|
---|
288 | test_method(c.do_string, (None, really_big_string), (really_big_string, None, really_big_string) )
|
---|
289 | test_method(c.do_string, (None, really_big_wstring), (really_big_string, None, really_big_string) )
|
---|
290 | test_method(c.do_wstring, ("Hello from ", "Python"), ("Hello from Python", "Hello from ", "Python") )
|
---|
291 | test_method(c.do_wstring, (u"Hello from ", u"Python"), ("Hello from Python", "Hello from ", "Python") )
|
---|
292 | test_method(c.do_string, (None, really_big_wstring), (really_big_wstring, None, really_big_wstring) )
|
---|
293 | test_method(c.do_string, (None, really_big_string), (really_big_wstring, None, really_big_wstring) )
|
---|
294 | test_method(c.do_nsIIDRef, (component_iid, new_iid), (component_iid, component_iid, new_iid))
|
---|
295 | test_method(c.do_nsIIDRef, (new_iid, component_iid), (new_iid, component_iid, component_iid))
|
---|
296 | test_method(c.do_nsIPythonTestInterface, (None, None), (None, None, c))
|
---|
297 | test_method(c.do_nsIPythonTestInterface, (c, c), (c, c, c))
|
---|
298 | test_method(c.do_nsISupports, (None, None), (c, None, None))
|
---|
299 | test_method(c.do_nsISupports, (c,c), (c, c, c))
|
---|
300 | test_method(c.do_nsISupportsIs, (xpcom._xpcom.IID_nsISupports,), c)
|
---|
301 | test_method(c.do_nsISupportsIs, (xpcom.components.interfaces.nsIPythonTestInterface,), c)
|
---|
302 | ## test_method(c.do_nsISupportsIs2, (xpcom.components.interfaces.nsIPythonTestInterface,c), (xpcom.components.interfaces.nsIPythonTestInterface,c))
|
---|
303 | ## test_method(c.do_nsISupportsIs3, (c,), (xpcom.components.interfaces.nsIPythonTestInterface,c))
|
---|
304 | ## test_method(c.do_nsISupportsIs4, (), (xpcom.components.interfaces.nsIPythonTestInterface,c))
|
---|
305 | # Test the constants.
|
---|
306 | test_constant(c, "One", 1)
|
---|
307 | test_constant(c, "Two", 2)
|
---|
308 | test_constant(c, "MinusOne", -1)
|
---|
309 | test_constant(c, "BigLong", 0x7FFFFFFF)
|
---|
310 | test_constant(c, "BiggerLong", -1)
|
---|
311 | test_constant(c, "BigULong", -1)
|
---|
312 | # Test the components.Interfaces semantics
|
---|
313 | i = xpcom.components.interfaces.nsIPythonTestInterface
|
---|
314 | test_constant(i, "One", 1)
|
---|
315 | test_constant(i, "Two", 2)
|
---|
316 | test_constant(i, "MinusOne", -1)
|
---|
317 | test_constant(i, "BigLong", 0x7FFFFFFF)
|
---|
318 | test_constant(i, "BigULong", -1)
|
---|
319 |
|
---|
320 | def test_derived_interface(c, test_flat = 0):
|
---|
321 | val = "Hello\0there"
|
---|
322 | expected = val * 2
|
---|
323 |
|
---|
324 | test_method(c.DoubleString, (val,), expected)
|
---|
325 | test_method(c.DoubleString2, (val,), expected)
|
---|
326 | test_method(c.DoubleString3, (val,), expected)
|
---|
327 | test_method(c.DoubleString4, (val,), expected)
|
---|
328 | test_method(c.UpString, (val,), val.upper())
|
---|
329 | test_method(c.UpString2, (val,), val.upper())
|
---|
330 | test_method(c.GetFixedString, (20,), "A"*20)
|
---|
331 | val = u"Hello\0there"
|
---|
332 | expected = val * 2
|
---|
333 | test_method(c.DoubleWideString, (val,), expected)
|
---|
334 | test_method(c.DoubleWideString2, (val,), expected)
|
---|
335 | test_method(c.DoubleWideString3, (val,), expected)
|
---|
336 | test_method(c.DoubleWideString4, (val,), expected)
|
---|
337 | test_method(c.UpWideString, (val,), val.upper())
|
---|
338 | test_method(c.UpWideString2, (val,), val.upper())
|
---|
339 | test_method(c.GetFixedWideString, (20,), u"A"*20)
|
---|
340 | val = extended_unicode_string
|
---|
341 | test_method(c.CopyUTF8String, ("foo",), "foo")
|
---|
342 | test_method(c.CopyUTF8String, (u"foo",), "foo")
|
---|
343 | test_method(c.CopyUTF8String, (val,), val)
|
---|
344 | test_method(c.CopyUTF8String, (val.encode("utf8"),), val)
|
---|
345 | test_method(c.CopyUTF8String2, ("foo",), "foo")
|
---|
346 | test_method(c.CopyUTF8String2, (u"foo",), "foo")
|
---|
347 | test_method(c.CopyUTF8String2, (val,), val)
|
---|
348 | test_method(c.CopyUTF8String2, (val.encode("utf8"),), val)
|
---|
349 | items = [1,2,3,4,5]
|
---|
350 | test_method(c.MultiplyEachItemInIntegerArray, (3, items,), map(lambda i:i*3, items))
|
---|
351 |
|
---|
352 | test_method(c.MultiplyEachItemInIntegerArrayAndAppend, (3, items), items + map(lambda i:i*3, items))
|
---|
353 | items = "Hello from Python".split()
|
---|
354 | expected = map( lambda x: x*2, items)
|
---|
355 | test_method(c.DoubleStringArray, (items,), expected)
|
---|
356 |
|
---|
357 | test_method(c.CompareStringArrays, (items, items), cmp(items, items))
|
---|
358 | # Can we pass lists and tuples correctly?
|
---|
359 | test_method(c.CompareStringArrays, (items, tuple(items)), cmp(items, items))
|
---|
360 | items2 = ["Not", "the", "same"]
|
---|
361 | test_method(c.CompareStringArrays, (items, items2), cmp(items, items2))
|
---|
362 |
|
---|
363 | expected = items[:]
|
---|
364 | expected.reverse()
|
---|
365 | test_method(c.ReverseStringArray, (items,), expected)
|
---|
366 |
|
---|
367 | expected = "Hello from the Python test component".split()
|
---|
368 | test_method(c.GetStrings, (), expected)
|
---|
369 |
|
---|
370 | val = "Hello\0there"
|
---|
371 | test_method(c.UpOctetArray, (val,), val.upper())
|
---|
372 | test_method(c.UpOctetArray, (unicode(val),), val.upper())
|
---|
373 | # Passing Unicode objects here used to cause us grief.
|
---|
374 | test_method(c.UpOctetArray2, (val,), val.upper())
|
---|
375 |
|
---|
376 | test_method(c.CheckInterfaceArray, ((c, c),), 1)
|
---|
377 | test_method(c.CheckInterfaceArray, ((c, None),), 0)
|
---|
378 | test_method(c.CheckInterfaceArray, ((),), 1)
|
---|
379 | test_method(c.CopyInterfaceArray, ((c, c),), [c,c])
|
---|
380 |
|
---|
381 | test_method(c.GetInterfaceArray, (), [c,c,c, None])
|
---|
382 | test_method(c.ExtendInterfaceArray, ((c,c,c, None),), [c,c,c,None,c,c,c,None] )
|
---|
383 |
|
---|
384 | expected = [xpcom.components.interfaces.nsIPythonTestInterfaceDOMStrings, xpcom.components.classes[contractid].clsid]
|
---|
385 | test_method(c.GetIIDArray, (), expected)
|
---|
386 |
|
---|
387 | val = [xpcom.components.interfaces.nsIPythonTestInterfaceExtra, xpcom.components.classes[contractid].clsid]
|
---|
388 | expected = val * 2
|
---|
389 | test_method(c.ExtendIIDArray, (val,), expected)
|
---|
390 |
|
---|
391 | test_method(c.GetArrays, (), ( [1,2,3], [4,5,6] ) )
|
---|
392 | test_method(c.CopyArray, ([1,2,3],), [1,2,3] )
|
---|
393 | test_method(c.CopyAndDoubleArray, ([1,2,3],), [1,2,3,1,2,3] )
|
---|
394 | test_method(c.AppendArray, ([1,2,3],), [1,2,3])
|
---|
395 | test_method(c.AppendArray, ([1,2,3],[4,5,6]), [1,2,3,4,5,6])
|
---|
396 |
|
---|
397 | test_method(c.CopyVariant, (None,), None)
|
---|
398 | test_method(c.CopyVariant, (1,), 1)
|
---|
399 | test_method(c.CopyVariant, (1.0,), 1.0)
|
---|
400 | test_method(c.CopyVariant, (-1,), -1)
|
---|
401 | test_method(c.CopyVariant, (sys.maxint+1,), sys.maxint+1)
|
---|
402 | test_method(c.CopyVariant, ("foo",), "foo")
|
---|
403 | test_method(c.CopyVariant, (u"foo",), u"foo")
|
---|
404 | test_method(c.CopyVariant, (c,), c)
|
---|
405 | test_method(c.CopyVariant, (component_iid,), component_iid)
|
---|
406 | test_method(c.CopyVariant, ((1,2),), [1,2])
|
---|
407 | test_method(c.CopyVariant, ((1.2,2.1),), [1.2,2.1])
|
---|
408 | test_method(c.CopyVariant, (("foo","bar"),), ["foo", "bar"])
|
---|
409 | test_method(c.CopyVariant, ((component_iid,component_iid),), [component_iid,component_iid])
|
---|
410 | test_method(c.CopyVariant, ((c,c),), [c,c])
|
---|
411 | sup = c.queryInterface(xpcom.components.interfaces.nsISupports)._comobj_
|
---|
412 | test_method(c.CopyVariant, ((sup, sup),), [sup,sup])
|
---|
413 | test_method(c.AppendVariant, (1,2), 3)
|
---|
414 | test_method(c.AppendVariant, ((1,2),(3,4)), 10)
|
---|
415 | test_method(c.AppendVariant, ("bar", "foo"), "foobar")
|
---|
416 | test_method(c.AppendVariant, (None, None), None)
|
---|
417 |
|
---|
418 | test_method(c.SumVariants, ([],), None)
|
---|
419 | # Array's dont expose their interface, so we are unable to auto-wrap
|
---|
420 | # variant arrays, as they aren't aware if the IID of the array
|
---|
421 | test_method(c.SumVariants, ([MakeVariant(1),MakeVariant(2),MakeVariant(3)],), 6)
|
---|
422 | test_method(c.SumVariants, ([MakeVariant('foo'), MakeVariant('bar')],), 'foobar')
|
---|
423 |
|
---|
424 | if not test_flat:
|
---|
425 | c = c.queryInterface(xpcom.components.interfaces.nsIPythonTestInterfaceDOMStrings)
|
---|
426 | # NULL DOM strings don't work yet.
|
---|
427 | # test_method(c.GetDOMStringResult, (-1,), None)
|
---|
428 | test_method(c.GetDOMStringResult, (3,), "PPP")
|
---|
429 | # test_method(c.GetDOMStringOut, (-1,), None)
|
---|
430 | test_method(c.GetDOMStringOut, (4,), "yyyy")
|
---|
431 | val = "Hello there"
|
---|
432 | test_method(c.GetDOMStringLength, (val,), len(val))
|
---|
433 | test_method(c.GetDOMStringRefLength, (val,), len(val))
|
---|
434 | test_method(c.GetDOMStringPtrLength, (val,), len(val))
|
---|
435 | test_method(c.ConcatDOMStrings, (val,val), val+val)
|
---|
436 | test_attribute(c, "domstring_value", "dom", "new dom")
|
---|
437 | if c.domstring_value_ro != "dom":
|
---|
438 | print "Read-only DOMString not correct - got", c.domstring_ro
|
---|
439 | try:
|
---|
440 | c.dom_string_ro = "new dom"
|
---|
441 | print "Managed to set a readonly attribute - eek!"
|
---|
442 | except AttributeError:
|
---|
443 | pass
|
---|
444 | except:
|
---|
445 | print "Unexpected exception when setting readonly attribute: %s: %s" % (sys.exc_info()[0], sys.exc_info()[1])
|
---|
446 | if c.domstring_value_ro != "dom":
|
---|
447 | print "Read-only DOMString not correct after failed set attempt - got", c.domstring_ro
|
---|
448 |
|
---|
449 | def do_test_failures():
|
---|
450 | c = xpcom.client.Component(contractid, xpcom.components.interfaces.nsIPythonTestInterfaceExtra)
|
---|
451 | try:
|
---|
452 | ret = c.do_nsISupportsIs( xpcom._xpcom.IID_nsIInterfaceInfoManager )
|
---|
453 | print "*** got", ret, "***"
|
---|
454 | raise RuntimeError, "We worked when using an IID we dont support!?!"
|
---|
455 | except xpcom.Exception, details:
|
---|
456 | if details.errno != xpcom.nsError.NS_ERROR_NO_INTERFACE:
|
---|
457 | raise RuntimeError, "Wrong COM exception type: %r" % (details,)
|
---|
458 |
|
---|
459 | def test_failures():
|
---|
460 | # This extra stack-frame ensures Python cleans up sys.last_traceback etc
|
---|
461 | do_test_failures()
|
---|
462 |
|
---|
463 | def test_all():
|
---|
464 | c = xpcom.client.Component(contractid, xpcom.components.interfaces.nsIPythonTestInterface)
|
---|
465 | test_base_interface(c)
|
---|
466 | # Now create an instance using the derived IID, and test that.
|
---|
467 | c = xpcom.client.Component(contractid, xpcom.components.interfaces.nsIPythonTestInterfaceExtra)
|
---|
468 | test_base_interface(c)
|
---|
469 | test_derived_interface(c)
|
---|
470 | # Now create an instance and test interface flattening.
|
---|
471 | c = xpcom.components.classes[contractid].createInstance()
|
---|
472 | test_base_interface(c)
|
---|
473 | test_derived_interface(c, test_flat=1)
|
---|
474 |
|
---|
475 | # We had a bug where a "set" of an attribute before a "get" failed.
|
---|
476 | # Don't let it happen again :)
|
---|
477 | c = xpcom.components.classes[contractid].createInstance()
|
---|
478 | c.boolean_value = 0
|
---|
479 |
|
---|
480 | # This name is used in exceptions etc - make sure we got it from nsIClassInfo OK.
|
---|
481 | assert c._object_name_ == "Python.TestComponent"
|
---|
482 |
|
---|
483 | test_failures()
|
---|
484 |
|
---|
485 | try:
|
---|
486 | from sys import gettotalrefcount
|
---|
487 | except ImportError:
|
---|
488 | # Not a Debug build - assume no references (can't be leaks then :-)
|
---|
489 | def gettotalrefcount():
|
---|
490 | return 0
|
---|
491 |
|
---|
492 | from pyxpcom_test_tools import getmemusage
|
---|
493 |
|
---|
494 | def test_from_js():
|
---|
495 | # Ensure we can find the js test script - same dir as this!
|
---|
496 | # Assume the path of sys.argv[0] is where we can find the js test code.
|
---|
497 | # (Running under the regression test is a little painful)
|
---|
498 | script_dir = os.path.split(sys.argv[0])[0]
|
---|
499 | fname = os.path.join( script_dir, "test_test_component.js")
|
---|
500 | if not os.path.isfile(fname):
|
---|
501 | raise RuntimeError, "Can not find '%s'" % (fname,)
|
---|
502 | # Note we _dont_ pump the test output out, as debug "xpcshell" spews
|
---|
503 | # extra debug info that will cause our output comparison to fail.
|
---|
504 | data = os.popen('xpcshell "' + fname + '"').readlines()
|
---|
505 | good = 0
|
---|
506 | for line in data:
|
---|
507 | if line.strip() == "javascript successfully tested the Python test component.":
|
---|
508 | good = 1
|
---|
509 | if not good:
|
---|
510 | print "** The javascript test appeared to fail! Test output follows **"
|
---|
511 | print "".join(data)
|
---|
512 | print "** End of javascript test output **"
|
---|
513 | raise RuntimeError, "test failed"
|
---|
514 |
|
---|
515 | def doit(num_loops = -1):
|
---|
516 | if "-v" in sys.argv: # Hack the verbose flag for the server
|
---|
517 | xpcom.verbose = 1
|
---|
518 | # Do the test lots of times - can help shake-out ref-count bugs.
|
---|
519 | if num_loops == -1: num_loops = 5
|
---|
520 | for i in xrange(num_loops):
|
---|
521 | test_all()
|
---|
522 |
|
---|
523 | if i==0:
|
---|
524 | # First loop is likely to "leak" as we cache things.
|
---|
525 | # Leaking after that is a problem.
|
---|
526 | if gc is not None:
|
---|
527 | gc.collect()
|
---|
528 | num_refs = gettotalrefcount()
|
---|
529 | mem_usage = getmemusage()
|
---|
530 |
|
---|
531 | if num_errors:
|
---|
532 | break
|
---|
533 |
|
---|
534 | if gc is not None:
|
---|
535 | gc.collect()
|
---|
536 |
|
---|
537 | lost = gettotalrefcount() - num_refs
|
---|
538 | # Sometimes we get spurious counts off by 1 or 2.
|
---|
539 | # This can't indicate a real leak, as we have looped
|
---|
540 | # more than twice!
|
---|
541 | if abs(lost)>3: # 2 or 3 :)
|
---|
542 | print "*** Lost %d references" % (lost,)
|
---|
543 |
|
---|
544 | # sleep to allow the OS to recover
|
---|
545 | time.sleep(1)
|
---|
546 | mem_lost = getmemusage() - mem_usage
|
---|
547 | # working set size is fickle, and when we were leaking strings, this test
|
---|
548 | # would report a leak of 100MB. So we allow a 3MB buffer - but even this
|
---|
549 | # may still occasionally report spurious warnings. If you are really
|
---|
550 | # worried, bump the counter to a huge value, and if there is a leak it will
|
---|
551 | # show.
|
---|
552 | if mem_lost > 3000000:
|
---|
553 | print "*** Lost %.6f MB of memory" % (mem_lost/1000000.0,)
|
---|
554 |
|
---|
555 | assert num_errors==0, "There were %d errors testing the Python component" % (num_errors,)
|
---|
556 |
|
---|
557 | def suite():
|
---|
558 | from pyxpcom_test_tools import suite_from_functions
|
---|
559 | return suite_from_functions(doit, test_from_js)
|
---|
560 |
|
---|
561 | if __name__=='__main__':
|
---|
562 | num_iters = 10 # times times is *lots* - we do a fair bit of work!
|
---|
563 | if __name__=='__main__' and len(sys.argv) > 1:
|
---|
564 | num_iters = int(sys.argv[1])
|
---|
565 |
|
---|
566 | print "Testing the Python.TestComponent component"
|
---|
567 | doit(num_iters)
|
---|
568 | print "The Python test component worked."
|
---|
569 | test_from_js()
|
---|
570 | print "JS successfully used our Python test component."
|
---|
571 | xpcom._xpcom.NS_ShutdownXPCOM()
|
---|
572 | ni = xpcom._xpcom._GetInterfaceCount()
|
---|
573 | ng = xpcom._xpcom._GetGatewayCount()
|
---|
574 | if ni or ng:
|
---|
575 | print "********* WARNING - Leaving with %d/%d objects alive" % (ni,ng)
|
---|