##// END OF EJS Templates
Use unittest2 for testing
marcink -
r3872:2b9da874 beta
parent child Browse files
Show More
@@ -1,550 +1,554 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.lib.compat
4 4 ~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Python backward compatibility functions and common libs
7 7
8 8
9 9 :created_on: Oct 7, 2011
10 10 :author: marcink
11 11 :copyright: (C) 2010-2010 Marcin Kuzminski <marcin@python-works.com>
12 12 :license: GPLv3, see COPYING for more details.
13 13 """
14 14 # This program is free software: you can redistribute it and/or modify
15 15 # it under the terms of the GNU General Public License as published by
16 16 # the Free Software Foundation, either version 3 of the License, or
17 17 # (at your option) any later version.
18 18 #
19 19 # This program is distributed in the hope that it will be useful,
20 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 22 # GNU General Public License for more details.
23 23 #
24 24 # You should have received a copy of the GNU General Public License
25 25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 26
27 27 import os
28 28 from rhodecode import __py_version__, is_windows
29 29
30 30 #==============================================================================
31 31 # json
32 32 #==============================================================================
33 33 from rhodecode.lib.ext_json import json
34 34
35 if __py_version__ >= (2, 7):
36 import unittest
37 else:
38 import unittest2 as unittest
35 39
36 40 #==============================================================================
37 41 # izip_longest
38 42 #==============================================================================
39 43 try:
40 44 from itertools import izip_longest
41 45 except ImportError:
42 46 import itertools
43 47
44 48 def izip_longest(*args, **kwds):
45 49 fillvalue = kwds.get("fillvalue")
46 50
47 51 def sentinel(counter=([fillvalue] * (len(args) - 1)).pop):
48 52 yield counter() # yields the fillvalue, or raises IndexError
49 53
50 54 fillers = itertools.repeat(fillvalue)
51 55 iters = [itertools.chain(it, sentinel(), fillers)
52 56 for it in args]
53 57 try:
54 58 for tup in itertools.izip(*iters):
55 59 yield tup
56 60 except IndexError:
57 61 pass
58 62
59 63
60 64 #==============================================================================
61 65 # OrderedDict
62 66 #==============================================================================
63 67
64 68 # Python Software Foundation License
65 69
66 70 # XXX: it feels like using the class with "is" and "is not" instead of "==" and
67 71 # "!=" should be faster.
68 72 class _Nil(object):
69 73
70 74 def __repr__(self):
71 75 return "nil"
72 76
73 77 def __eq__(self, other):
74 78 if (isinstance(other, _Nil)):
75 79 return True
76 80 else:
77 81 return NotImplemented
78 82
79 83 def __ne__(self, other):
80 84 if (isinstance(other, _Nil)):
81 85 return False
82 86 else:
83 87 return NotImplemented
84 88
85 89 _nil = _Nil()
86 90
87 91
88 92 class _odict(object):
89 93 """Ordered dict data structure, with O(1) complexity for dict operations
90 94 that modify one element.
91 95
92 96 Overwriting values doesn't change their original sequential order.
93 97 """
94 98
95 99 def _dict_impl(self):
96 100 return None
97 101
98 102 def __init__(self, data=(), **kwds):
99 103 """This doesn't accept keyword initialization as normal dicts to avoid
100 104 a trap - inside a function or method the keyword args are accessible
101 105 only as a dict, without a defined order, so their original order is
102 106 lost.
103 107 """
104 108 if kwds:
105 109 raise TypeError("__init__() of ordered dict takes no keyword "
106 110 "arguments to avoid an ordering trap.")
107 111 self._dict_impl().__init__(self)
108 112 # If you give a normal dict, then the order of elements is undefined
109 113 if hasattr(data, "iteritems"):
110 114 for key, val in data.iteritems():
111 115 self[key] = val
112 116 else:
113 117 for key, val in data:
114 118 self[key] = val
115 119
116 120 # Double-linked list header
117 121 def _get_lh(self):
118 122 dict_impl = self._dict_impl()
119 123 if not hasattr(self, '_lh'):
120 124 dict_impl.__setattr__(self, '_lh', _nil)
121 125 return dict_impl.__getattribute__(self, '_lh')
122 126
123 127 def _set_lh(self, val):
124 128 self._dict_impl().__setattr__(self, '_lh', val)
125 129
126 130 lh = property(_get_lh, _set_lh)
127 131
128 132 # Double-linked list tail
129 133 def _get_lt(self):
130 134 dict_impl = self._dict_impl()
131 135 if not hasattr(self, '_lt'):
132 136 dict_impl.__setattr__(self, '_lt', _nil)
133 137 return dict_impl.__getattribute__(self, '_lt')
134 138
135 139 def _set_lt(self, val):
136 140 self._dict_impl().__setattr__(self, '_lt', val)
137 141
138 142 lt = property(_get_lt, _set_lt)
139 143
140 144 def __getitem__(self, key):
141 145 return self._dict_impl().__getitem__(self, key)[1]
142 146
143 147 def __setitem__(self, key, val):
144 148 dict_impl = self._dict_impl()
145 149 try:
146 150 dict_impl.__getitem__(self, key)[1] = val
147 151 except KeyError:
148 152 new = [dict_impl.__getattribute__(self, 'lt'), val, _nil]
149 153 dict_impl.__setitem__(self, key, new)
150 154 if dict_impl.__getattribute__(self, 'lt') == _nil:
151 155 dict_impl.__setattr__(self, 'lh', key)
152 156 else:
153 157 dict_impl.__getitem__(
154 158 self, dict_impl.__getattribute__(self, 'lt'))[2] = key
155 159 dict_impl.__setattr__(self, 'lt', key)
156 160
157 161 def __delitem__(self, key):
158 162 dict_impl = self._dict_impl()
159 163 pred, _, succ = self._dict_impl().__getitem__(self, key)
160 164 if pred == _nil:
161 165 dict_impl.__setattr__(self, 'lh', succ)
162 166 else:
163 167 dict_impl.__getitem__(self, pred)[2] = succ
164 168 if succ == _nil:
165 169 dict_impl.__setattr__(self, 'lt', pred)
166 170 else:
167 171 dict_impl.__getitem__(self, succ)[0] = pred
168 172 dict_impl.__delitem__(self, key)
169 173
170 174 def __contains__(self, key):
171 175 return key in self.keys()
172 176
173 177 def __len__(self):
174 178 return len(self.keys())
175 179
176 180 def __str__(self):
177 181 pairs = ("%r: %r" % (k, v) for k, v in self.iteritems())
178 182 return "{%s}" % ", ".join(pairs)
179 183
180 184 def __repr__(self):
181 185 if self:
182 186 pairs = ("(%r, %r)" % (k, v) for k, v in self.iteritems())
183 187 return "odict([%s])" % ", ".join(pairs)
184 188 else:
185 189 return "odict()"
186 190
187 191 def get(self, k, x=None):
188 192 if k in self:
189 193 return self._dict_impl().__getitem__(self, k)[1]
190 194 else:
191 195 return x
192 196
193 197 def __iter__(self):
194 198 dict_impl = self._dict_impl()
195 199 curr_key = dict_impl.__getattribute__(self, 'lh')
196 200 while curr_key != _nil:
197 201 yield curr_key
198 202 curr_key = dict_impl.__getitem__(self, curr_key)[2]
199 203
200 204 iterkeys = __iter__
201 205
202 206 def keys(self):
203 207 return list(self.iterkeys())
204 208
205 209 def itervalues(self):
206 210 dict_impl = self._dict_impl()
207 211 curr_key = dict_impl.__getattribute__(self, 'lh')
208 212 while curr_key != _nil:
209 213 _, val, curr_key = dict_impl.__getitem__(self, curr_key)
210 214 yield val
211 215
212 216 def values(self):
213 217 return list(self.itervalues())
214 218
215 219 def iteritems(self):
216 220 dict_impl = self._dict_impl()
217 221 curr_key = dict_impl.__getattribute__(self, 'lh')
218 222 while curr_key != _nil:
219 223 _, val, next_key = dict_impl.__getitem__(self, curr_key)
220 224 yield curr_key, val
221 225 curr_key = next_key
222 226
223 227 def items(self):
224 228 return list(self.iteritems())
225 229
226 230 def sort(self, cmp=None, key=None, reverse=False):
227 231 items = [(k, v) for k, v in self.items()]
228 232 if cmp is not None:
229 233 items = sorted(items, cmp=cmp)
230 234 elif key is not None:
231 235 items = sorted(items, key=key)
232 236 else:
233 237 items = sorted(items, key=lambda x: x[1])
234 238 if reverse:
235 239 items.reverse()
236 240 self.clear()
237 241 self.__init__(items)
238 242
239 243 def clear(self):
240 244 dict_impl = self._dict_impl()
241 245 dict_impl.clear(self)
242 246 dict_impl.__setattr__(self, 'lh', _nil)
243 247 dict_impl.__setattr__(self, 'lt', _nil)
244 248
245 249 def copy(self):
246 250 return self.__class__(self)
247 251
248 252 def update(self, data=(), **kwds):
249 253 if kwds:
250 254 raise TypeError("update() of ordered dict takes no keyword "
251 255 "arguments to avoid an ordering trap.")
252 256 if hasattr(data, "iteritems"):
253 257 data = data.iteritems()
254 258 for key, val in data:
255 259 self[key] = val
256 260
257 261 def setdefault(self, k, x=None):
258 262 try:
259 263 return self[k]
260 264 except KeyError:
261 265 self[k] = x
262 266 return x
263 267
264 268 def pop(self, k, x=_nil):
265 269 try:
266 270 val = self[k]
267 271 del self[k]
268 272 return val
269 273 except KeyError:
270 274 if x == _nil:
271 275 raise
272 276 return x
273 277
274 278 def popitem(self):
275 279 try:
276 280 dict_impl = self._dict_impl()
277 281 key = dict_impl.__getattribute__(self, 'lt')
278 282 return key, self.pop(key)
279 283 except KeyError:
280 284 raise KeyError("'popitem(): ordered dictionary is empty'")
281 285
282 286 def riterkeys(self):
283 287 """To iterate on keys in reversed order.
284 288 """
285 289 dict_impl = self._dict_impl()
286 290 curr_key = dict_impl.__getattribute__(self, 'lt')
287 291 while curr_key != _nil:
288 292 yield curr_key
289 293 curr_key = dict_impl.__getitem__(self, curr_key)[0]
290 294
291 295 __reversed__ = riterkeys
292 296
293 297 def rkeys(self):
294 298 """List of the keys in reversed order.
295 299 """
296 300 return list(self.riterkeys())
297 301
298 302 def ritervalues(self):
299 303 """To iterate on values in reversed order.
300 304 """
301 305 dict_impl = self._dict_impl()
302 306 curr_key = dict_impl.__getattribute__(self, 'lt')
303 307 while curr_key != _nil:
304 308 curr_key, val, _ = dict_impl.__getitem__(self, curr_key)
305 309 yield val
306 310
307 311 def rvalues(self):
308 312 """List of the values in reversed order.
309 313 """
310 314 return list(self.ritervalues())
311 315
312 316 def riteritems(self):
313 317 """To iterate on (key, value) in reversed order.
314 318 """
315 319 dict_impl = self._dict_impl()
316 320 curr_key = dict_impl.__getattribute__(self, 'lt')
317 321 while curr_key != _nil:
318 322 pred_key, val, _ = dict_impl.__getitem__(self, curr_key)
319 323 yield curr_key, val
320 324 curr_key = pred_key
321 325
322 326 def ritems(self):
323 327 """List of the (key, value) in reversed order.
324 328 """
325 329 return list(self.riteritems())
326 330
327 331 def firstkey(self):
328 332 if self:
329 333 return self._dict_impl().__getattribute__(self, 'lh')
330 334 else:
331 335 raise KeyError("'firstkey(): ordered dictionary is empty'")
332 336
333 337 def lastkey(self):
334 338 if self:
335 339 return self._dict_impl().__getattribute__(self, 'lt')
336 340 else:
337 341 raise KeyError("'lastkey(): ordered dictionary is empty'")
338 342
339 343 def as_dict(self):
340 344 return self._dict_impl()(self.items())
341 345
342 346 def _repr(self):
343 347 """_repr(): low level repr of the whole data contained in the odict.
344 348 Useful for debugging.
345 349 """
346 350 dict_impl = self._dict_impl()
347 351 form = "odict low level repr lh,lt,data: %r, %r, %s"
348 352 return form % (dict_impl.__getattribute__(self, 'lh'),
349 353 dict_impl.__getattribute__(self, 'lt'),
350 354 dict_impl.__repr__(self))
351 355
352 356
353 357 class OrderedDict(_odict, dict):
354 358
355 359 def _dict_impl(self):
356 360 return dict
357 361
358 362
359 363 #==============================================================================
360 364 # OrderedSet
361 365 #==============================================================================
362 366 from sqlalchemy.util import OrderedSet
363 367
364 368
365 369 #==============================================================================
366 370 # kill FUNCTIONS
367 371 #==============================================================================
368 372 if is_windows:
369 373 import ctypes
370 374
371 375 def kill(pid, sig):
372 376 """kill function for Win32"""
373 377 kernel32 = ctypes.windll.kernel32
374 378 handle = kernel32.OpenProcess(1, 0, pid)
375 379 return (0 != kernel32.TerminateProcess(handle, 0))
376 380
377 381 else:
378 382 kill = os.kill
379 383
380 384
381 385 #==============================================================================
382 386 # itertools.product
383 387 #==============================================================================
384 388
385 389 try:
386 390 from itertools import product
387 391 except ImportError:
388 392 def product(*args, **kwds):
389 393 # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
390 394 # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
391 395 pools = map(tuple, args) * kwds.get('repeat', 1)
392 396 result = [[]]
393 397 for pool in pools:
394 398 result = [x + [y] for x in result for y in pool]
395 399 for prod in result:
396 400 yield tuple(prod)
397 401
398 402
399 403 #==============================================================================
400 404 # BytesIO
401 405 #==============================================================================
402 406
403 407 try:
404 408 from io import BytesIO
405 409 except ImportError:
406 410 from cStringIO import StringIO as BytesIO
407 411
408 412
409 413 #==============================================================================
410 414 # bytes
411 415 #==============================================================================
412 416 if __py_version__ >= (2, 6):
413 417 _bytes = bytes
414 418 else:
415 419 # in py2.6 bytes is a synonim for str
416 420 _bytes = str
417 421
418 422 if __py_version__ >= (2, 6):
419 423 _bytearray = bytearray
420 424 else:
421 425 import array
422 426 # no idea if this is correct but all integration tests are passing
423 427 # i think we never use bytearray anyway
424 428 _bytearray = array
425 429
426 430
427 431 #==============================================================================
428 432 # deque
429 433 #==============================================================================
430 434
431 435 if __py_version__ >= (2, 6):
432 436 from collections import deque
433 437 else:
434 438 #need to implement our own deque with maxlen
435 439 class deque(object):
436 440
437 441 def __init__(self, iterable=(), maxlen= -1):
438 442 if not hasattr(self, 'data'):
439 443 self.left = self.right = 0
440 444 self.data = {}
441 445 self.maxlen = maxlen or -1
442 446 self.extend(iterable)
443 447
444 448 def append(self, x):
445 449 self.data[self.right] = x
446 450 self.right += 1
447 451 if self.maxlen != -1 and len(self) > self.maxlen:
448 452 self.popleft()
449 453
450 454 def appendleft(self, x):
451 455 self.left -= 1
452 456 self.data[self.left] = x
453 457 if self.maxlen != -1 and len(self) > self.maxlen:
454 458 self.pop()
455 459
456 460 def pop(self):
457 461 if self.left == self.right:
458 462 raise IndexError('cannot pop from empty deque')
459 463 self.right -= 1
460 464 elem = self.data[self.right]
461 465 del self.data[self.right]
462 466 return elem
463 467
464 468 def popleft(self):
465 469 if self.left == self.right:
466 470 raise IndexError('cannot pop from empty deque')
467 471 elem = self.data[self.left]
468 472 del self.data[self.left]
469 473 self.left += 1
470 474 return elem
471 475
472 476 def clear(self):
473 477 self.data.clear()
474 478 self.left = self.right = 0
475 479
476 480 def extend(self, iterable):
477 481 for elem in iterable:
478 482 self.append(elem)
479 483
480 484 def extendleft(self, iterable):
481 485 for elem in iterable:
482 486 self.appendleft(elem)
483 487
484 488 def rotate(self, n=1):
485 489 if self:
486 490 n %= len(self)
487 491 for i in xrange(n):
488 492 self.appendleft(self.pop())
489 493
490 494 def __getitem__(self, i):
491 495 if i < 0:
492 496 i += len(self)
493 497 try:
494 498 return self.data[i + self.left]
495 499 except KeyError:
496 500 raise IndexError
497 501
498 502 def __setitem__(self, i, value):
499 503 if i < 0:
500 504 i += len(self)
501 505 try:
502 506 self.data[i + self.left] = value
503 507 except KeyError:
504 508 raise IndexError
505 509
506 510 def __delitem__(self, i):
507 511 size = len(self)
508 512 if not (-size <= i < size):
509 513 raise IndexError
510 514 data = self.data
511 515 if i < 0:
512 516 i += size
513 517 for j in xrange(self.left + i, self.right - 1):
514 518 data[j] = data[j + 1]
515 519 self.pop()
516 520
517 521 def __len__(self):
518 522 return self.right - self.left
519 523
520 524 def __cmp__(self, other):
521 525 if type(self) != type(other):
522 526 return cmp(type(self), type(other))
523 527 return cmp(list(self), list(other))
524 528
525 529 def __repr__(self, _track=[]):
526 530 if id(self) in _track:
527 531 return '...'
528 532 _track.append(id(self))
529 533 r = 'deque(%r, maxlen=%s)' % (list(self), self.maxlen)
530 534 _track.remove(id(self))
531 535 return r
532 536
533 537 def __getstate__(self):
534 538 return (tuple(self),)
535 539
536 540 def __setstate__(self, s):
537 541 self.__init__(s[0])
538 542
539 543 def __hash__(self):
540 544 raise TypeError
541 545
542 546 def __copy__(self):
543 547 return self.__class__(self)
544 548
545 549 def __deepcopy__(self, memo={}):
546 550 from copy import deepcopy
547 551 result = self.__class__()
548 552 memo[id(self)] = result
549 553 result.__init__(deepcopy(tuple(self), memo))
550 554 return result
@@ -1,202 +1,202 b''
1 1 """Pylons application test package
2 2
3 3 This package assumes the Pylons environment is already loaded, such as
4 4 when this script is imported from the `nosetests --with-pylons=test.ini`
5 5 command.
6 6
7 7 This module initializes the application via ``websetup`` (`paster
8 8 setup-app`) and provides the base testing objects.
9 9
10 10 nosetests -x - fail on first error
11 11 nosetests rhodecode.tests.functional.test_admin_settings:TestSettingsController.test_my_account
12 12 nosetests --pdb --pdb-failures
13 13 nosetests --with-coverage --cover-package=rhodecode.model.validators rhodecode.tests.test_validators
14 14
15 15 optional FLAGS:
16 16 RC_WHOOSH_TEST_DISABLE=1 - skip whoosh index building and tests
17 17 RC_NO_TMP_PATH=1 - disable new temp path for tests, used mostly for test_vcs_operations
18 18
19 19 """
20 20 import os
21 21 import time
22 22 import logging
23 23 import datetime
24 24 import hashlib
25 25 import tempfile
26 26 from os.path import join as jn
27 27
28 from unittest import TestCase
29 28 from tempfile import _RandomNameSequence
30 29
31 30 from paste.deploy import loadapp
32 31 from paste.script.appinstall import SetupCommand
33 32
34 33 import pylons
35 34 import pylons.test
36 35 from pylons import config, url
37 36 from pylons.i18n.translation import _get_translator
38 37 from pylons.util import ContextObj
39 38
40 39 from routes.util import URLGenerator
41 40 from webtest import TestApp
42 41 from nose.plugins.skip import SkipTest
43 42
43 from rhodecode.lib.compat import unittest
44 44 from rhodecode import is_windows
45 45 from rhodecode.model.meta import Session
46 46 from rhodecode.model.db import User
47 47 from rhodecode.tests.nose_parametrized import parameterized
48 48 from rhodecode.lib.utils2 import safe_unicode, safe_str
49 49
50 50
51 51 os.environ['TZ'] = 'UTC'
52 52 if not is_windows:
53 53 time.tzset()
54 54
55 55 log = logging.getLogger(__name__)
56 56
57 57 __all__ = [
58 58 'parameterized', 'environ', 'url', 'get_new_dir', 'TestController',
59 59 'SkipTest', 'ldap_lib_installed', 'BaseTestCase', 'init_stack',
60 60 'TESTS_TMP_PATH', 'HG_REPO', 'GIT_REPO', 'NEW_HG_REPO', 'NEW_GIT_REPO',
61 61 'HG_FORK', 'GIT_FORK', 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_ADMIN_PASS',
62 62 'TEST_USER_REGULAR_LOGIN', 'TEST_USER_REGULAR_PASS',
63 63 'TEST_USER_REGULAR_EMAIL', 'TEST_USER_REGULAR2_LOGIN',
64 64 'TEST_USER_REGULAR2_PASS', 'TEST_USER_REGULAR2_EMAIL', 'TEST_HG_REPO',
65 65 'TEST_HG_REPO_CLONE', 'TEST_HG_REPO_PULL', 'TEST_GIT_REPO',
66 66 'TEST_GIT_REPO_CLONE', 'TEST_GIT_REPO_PULL', 'HG_REMOTE_REPO',
67 67 'GIT_REMOTE_REPO', 'SCM_TESTS',
68 68 ]
69 69
70 70 # Invoke websetup with the current config file
71 71 # SetupCommand('setup-app').run([config_file])
72 72
73 73 environ = {}
74 74
75 75 #SOME GLOBALS FOR TESTS
76 76
77 77 TESTS_TMP_PATH = jn('/', 'tmp', 'rc_test_%s' % _RandomNameSequence().next())
78 78 TEST_USER_ADMIN_LOGIN = 'test_admin'
79 79 TEST_USER_ADMIN_PASS = 'test12'
80 80 TEST_USER_ADMIN_EMAIL = 'test_admin@mail.com'
81 81
82 82 TEST_USER_REGULAR_LOGIN = 'test_regular'
83 83 TEST_USER_REGULAR_PASS = 'test12'
84 84 TEST_USER_REGULAR_EMAIL = 'test_regular@mail.com'
85 85
86 86 TEST_USER_REGULAR2_LOGIN = 'test_regular2'
87 87 TEST_USER_REGULAR2_PASS = 'test12'
88 88 TEST_USER_REGULAR2_EMAIL = 'test_regular2@mail.com'
89 89
90 90 HG_REPO = 'vcs_test_hg'
91 91 GIT_REPO = 'vcs_test_git'
92 92
93 93 NEW_HG_REPO = 'vcs_test_hg_new'
94 94 NEW_GIT_REPO = 'vcs_test_git_new'
95 95
96 96 HG_FORK = 'vcs_test_hg_fork'
97 97 GIT_FORK = 'vcs_test_git_fork'
98 98
99 99 ## VCS
100 100 SCM_TESTS = ['hg', 'git']
101 101 uniq_suffix = str(int(time.mktime(datetime.datetime.now().timetuple())))
102 102
103 103 GIT_REMOTE_REPO = 'git://github.com/codeinn/vcs.git'
104 104
105 105 TEST_GIT_REPO = jn(TESTS_TMP_PATH, GIT_REPO)
106 106 TEST_GIT_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcsgitclone%s' % uniq_suffix)
107 107 TEST_GIT_REPO_PULL = jn(TESTS_TMP_PATH, 'vcsgitpull%s' % uniq_suffix)
108 108
109 109
110 110 HG_REMOTE_REPO = 'http://bitbucket.org/marcinkuzminski/vcs'
111 111
112 112 TEST_HG_REPO = jn(TESTS_TMP_PATH, HG_REPO)
113 113 TEST_HG_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcshgclone%s' % uniq_suffix)
114 114 TEST_HG_REPO_PULL = jn(TESTS_TMP_PATH, 'vcshgpull%s' % uniq_suffix)
115 115
116 116 TEST_DIR = tempfile.gettempdir()
117 117 TEST_REPO_PREFIX = 'vcs-test'
118 118
119 119 # cached repos if any !
120 120 # comment out to get some other repos from bb or github
121 121 GIT_REMOTE_REPO = jn(TESTS_TMP_PATH, GIT_REPO)
122 122 HG_REMOTE_REPO = jn(TESTS_TMP_PATH, HG_REPO)
123 123
124 124 #skip ldap tests if LDAP lib is not installed
125 125 ldap_lib_installed = False
126 126 try:
127 127 import ldap
128 128 ldap_lib_installed = True
129 129 except ImportError:
130 130 # means that python-ldap is not installed
131 131 pass
132 132
133 133
134 134 def get_new_dir(title):
135 135 """
136 136 Returns always new directory path.
137 137 """
138 138 from rhodecode.tests.vcs.utils import get_normalized_path
139 139 name = TEST_REPO_PREFIX
140 140 if title:
141 141 name = '-'.join((name, title))
142 142 hex = hashlib.sha1(str(time.time())).hexdigest()
143 143 name = '-'.join((name, hex))
144 144 path = os.path.join(TEST_DIR, name)
145 145 return get_normalized_path(path)
146 146
147 147
148 148 def init_stack(config=None):
149 149 if not config:
150 150 config = pylons.test.pylonsapp.config
151 151 url._push_object(URLGenerator(config['routes.map'], environ))
152 152 pylons.app_globals._push_object(config['pylons.app_globals'])
153 153 pylons.config._push_object(config)
154 154 pylons.tmpl_context._push_object(ContextObj())
155 155 # Initialize a translator for tests that utilize i18n
156 156 translator = _get_translator(pylons.config.get('lang'))
157 157 pylons.translator._push_object(translator)
158 158
159 159
160 class BaseTestCase(TestCase):
160 class BaseTestCase(unittest.TestCase):
161 161 def __init__(self, *args, **kwargs):
162 162 self.wsgiapp = pylons.test.pylonsapp
163 163 init_stack(self.wsgiapp.config)
164 TestCase.__init__(self, *args, **kwargs)
164 unittest.TestCase.__init__(self, *args, **kwargs)
165 165
166 166
167 167 class TestController(BaseTestCase):
168 168
169 169 def __init__(self, *args, **kwargs):
170 170 BaseTestCase.__init__(self, *args, **kwargs)
171 171 self.app = TestApp(self.wsgiapp)
172 172 self.index_location = config['app_conf']['index_dir']
173 173
174 174 def log_user(self, username=TEST_USER_ADMIN_LOGIN,
175 175 password=TEST_USER_ADMIN_PASS):
176 176 self._logged_username = username
177 177 response = self.app.post(url(controller='login', action='index'),
178 178 {'username': username,
179 179 'password': password})
180 180
181 181 if 'invalid user name' in response.body:
182 182 self.fail('could not login using %s %s' % (username, password))
183 183
184 184 self.assertEqual(response.status, '302 Found')
185 185 ses = response.session['rhodecode_user']
186 186 self.assertEqual(ses.get('username'), username)
187 187 response = response.follow()
188 188 self.assertEqual(ses.get('is_authenticated'), True)
189 189
190 190 return response.session['rhodecode_user']
191 191
192 192 def _get_logged_user(self):
193 193 return User.get_by_username(self._logged_username)
194 194
195 195 def checkSessionFlash(self, response, msg):
196 196 self.assertTrue('flash' in response.session,
197 197 msg='Response session:%r have no flash'
198 198 % response.session)
199 199 if not msg in response.session['flash'][0][1]:
200 200 msg = u'msg `%s` not found in session flash: got `%s` instead' % (
201 201 msg, response.session['flash'][0][1])
202 202 self.fail(safe_str(msg))
General Comments 0
You need to be logged in to leave comments. Login now