OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 import ast | 6 import ast |
7 import datetime | 7 import datetime |
| 8 import hashlib |
| 9 import hmac |
| 10 import json |
8 import os | 11 import os |
| 12 import random |
| 13 import time |
9 import unittest | 14 import unittest |
10 | 15 |
11 import app | 16 import app |
| 17 from third_party.BeautifulSoup.BeautifulSoup import BeautifulSoup |
12 | 18 |
13 | 19 |
14 TEST_DIR = os.path.join(os.path.dirname(__file__), 'tests') | 20 TEST_DIR = os.path.join(os.path.dirname(__file__), 'tests') |
15 | 21 |
16 | 22 |
17 class GaeTestCase(unittest.TestCase): | 23 class GaeTestCase(unittest.TestCase): |
18 def setUp(self, *args, **kwargs): | 24 def setUp(self, *args, **kwargs): |
19 self.clear_datastore() | 25 self.clear_datastore() |
20 super(GaeTestCase, self).setUp(*args, **kwargs) | 26 super(GaeTestCase, self).setUp(*args, **kwargs) |
21 | 27 |
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 page = app.get_and_cache_pagedata('chromium/console') | 472 page = app.get_and_cache_pagedata('chromium/console') |
467 # Uncomment if deeper inspection is needed of the returned console. | 473 # Uncomment if deeper inspection is needed of the returned console. |
468 # with open(os.path.join(test_dir, 'expected.html'), 'w') as fh: | 474 # with open(os.path.join(test_dir, 'expected.html'), 'w') as fh: |
469 # fh.write(page['content']) | 475 # fh.write(page['content']) |
470 self.assertEquals('interface', page['body_class']) | 476 self.assertEquals('interface', page['body_class']) |
471 self.assertEquals(expected_content, page['content']) | 477 self.assertEquals(expected_content, page['content']) |
472 self.assertEquals( | 478 self.assertEquals( |
473 'http://build.chromium.org/p/chromium/console/../', | 479 'http://build.chromium.org/p/chromium/console/../', |
474 page['offsite_base']) | 480 page['offsite_base']) |
475 self.assertEquals('BuildBot: Chromium', page['title']) | 481 self.assertEquals('BuildBot: Chromium', page['title']) |
| 482 |
| 483 |
| 484 class MailTestCase(GaeTestCase): |
| 485 def setUp(self): |
| 486 self.test_dir = os.path.join(TEST_DIR, 'test_mailer') |
| 487 with open(os.path.join(self.test_dir, 'input.json')) as f: |
| 488 self.input_json = json.load(f) |
| 489 self.build_data = json.loads(self.input_json['message']) |
| 490 |
| 491 @staticmethod |
| 492 def _hash_message(mytime, message, url, secret): |
| 493 salt = random.getrandbits(32) |
| 494 hasher = hmac.new(secret, '%s:%d:%d' % (message, mytime, salt), |
| 495 hashlib.sha256) |
| 496 client_hash = hasher.hexdigest() |
| 497 |
| 498 return {'message': message, |
| 499 'time': mytime, |
| 500 'salt': salt, |
| 501 'url': url, |
| 502 'sha256': client_hash, |
| 503 } |
| 504 |
| 505 def test_html_format(self): |
| 506 import gatekeeper_mailer |
| 507 template = gatekeeper_mailer.MailTemplate(self.build_data['waterfall_url'], |
| 508 self.build_data['build_url'], |
| 509 self.build_data['project_name'], |
| 510 'test@chromium.org') |
| 511 |
| 512 _, html_content, _ = template.genMessageContent(self.build_data) |
| 513 |
| 514 with open(os.path.join(self.test_dir, 'expected.html')) as f: |
| 515 expected_html = ' '.join(f.read().splitlines()) |
| 516 |
| 517 self.assertEquals(' '.join(str(BeautifulSoup(html_content)).split()), |
| 518 ' '.join(str(BeautifulSoup(expected_html)).split())) |
| 519 |
| 520 def test_hmac_validation(self): |
| 521 from mailer import Email |
| 522 message = self.input_json['message'] |
| 523 url = 'http://invalid.chromium.org' |
| 524 secret = 'pajamas' |
| 525 |
| 526 test_json = self._hash_message(time.time(), message, url, secret) |
| 527 # pylint: disable=W0212 |
| 528 self.assertTrue(Email._validate_message(test_json, url, secret)) |
| 529 |
| 530 # Test that a trailing slash doesn't affect URL parsing. |
| 531 test_json = self._hash_message(time.time(), message, url + '/', secret) |
| 532 # pylint: disable=W0212 |
| 533 self.assertTrue(Email._validate_message(test_json, url, secret)) |
| 534 |
| 535 tests = [ |
| 536 self._hash_message(time.time() + 61, message, url, secret), |
| 537 self._hash_message(time.time() - 61, message, url, secret), |
| 538 self._hash_message(time.time(), message, url + 'hey', secret), |
| 539 self._hash_message(time.time(), message, url, secret + 'hey'), |
| 540 ] |
| 541 |
| 542 for test_json in tests: |
| 543 # pylint: disable=W0212 |
| 544 self.assertFalse(Email._validate_message(test_json, url, secret)) |
| 545 |
| 546 test_json = self._hash_message(time.time(), message, url, secret) |
| 547 test_json['message'] = test_json['message'] + 'hey' |
| 548 # pylint: disable=W0212 |
| 549 self.assertFalse(Email._validate_message(test_json, url, secret)) |
OLD | NEW |