michael@0: #!/usr/bin/env python michael@0: michael@0: # This Source Code Form is subject to the terms of the Mozilla Public michael@0: # License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: # You can obtain one at http://mozilla.org/MPL/2.0/. michael@0: michael@0: import os michael@0: import shutil michael@0: import tempfile michael@0: import unittest michael@0: from manifestparser import convert michael@0: from manifestparser import ManifestParser michael@0: from StringIO import StringIO michael@0: michael@0: here = os.path.dirname(os.path.abspath(__file__)) michael@0: michael@0: class TestManifestParser(unittest.TestCase): michael@0: """ michael@0: Test the manifest parser michael@0: michael@0: You must have ManifestDestiny installed before running these tests. michael@0: Run ``python manifestparser.py setup develop`` with setuptools installed. michael@0: """ michael@0: michael@0: def test_sanity(self): michael@0: """Ensure basic parser is sane""" michael@0: michael@0: parser = ManifestParser() michael@0: mozmill_example = os.path.join(here, 'mozmill-example.ini') michael@0: parser.read(mozmill_example) michael@0: tests = parser.tests michael@0: self.assertEqual(len(tests), len(file(mozmill_example).read().strip().splitlines())) michael@0: michael@0: # Ensure that capitalization and order aren't an issue: michael@0: lines = ['[%s]' % test['name'] for test in tests] michael@0: self.assertEqual(lines, file(mozmill_example).read().strip().splitlines()) michael@0: michael@0: # Show how you select subsets of tests: michael@0: mozmill_restart_example = os.path.join(here, 'mozmill-restart-example.ini') michael@0: parser.read(mozmill_restart_example) michael@0: restart_tests = parser.get(type='restart') michael@0: self.assertTrue(len(restart_tests) < len(parser.tests)) michael@0: self.assertEqual(len(restart_tests), len(parser.get(manifest=mozmill_restart_example))) michael@0: self.assertFalse([test for test in restart_tests michael@0: if test['manifest'] != os.path.join(here, 'mozmill-restart-example.ini')]) michael@0: self.assertEqual(parser.get('name', tags=['foo']), michael@0: ['restartTests/testExtensionInstallUninstall/test2.js', michael@0: 'restartTests/testExtensionInstallUninstall/test1.js']) michael@0: self.assertEqual(parser.get('name', foo='bar'), michael@0: ['restartTests/testExtensionInstallUninstall/test2.js']) michael@0: michael@0: def test_include(self): michael@0: """Illustrate how include works""" michael@0: michael@0: include_example = os.path.join(here, 'include-example.ini') michael@0: parser = ManifestParser(manifests=(include_example,)) michael@0: michael@0: # All of the tests should be included, in order: michael@0: self.assertEqual(parser.get('name'), michael@0: ['crash-handling', 'fleem', 'flowers']) michael@0: self.assertEqual([(test['name'], os.path.basename(test['manifest'])) for test in parser.tests], michael@0: [('crash-handling', 'bar.ini'), ('fleem', 'include-example.ini'), ('flowers', 'foo.ini')]) michael@0: michael@0: michael@0: # The manifests should be there too: michael@0: self.assertEqual(len(parser.manifests()), 3) michael@0: michael@0: # We already have the root directory: michael@0: self.assertEqual(here, parser.rootdir) michael@0: michael@0: michael@0: # DEFAULT values should persist across includes, unless they're michael@0: # overwritten. In this example, include-example.ini sets foo=bar, but michael@0: # it's overridden to fleem in bar.ini michael@0: self.assertEqual(parser.get('name', foo='bar'), michael@0: ['fleem', 'flowers']) michael@0: self.assertEqual(parser.get('name', foo='fleem'), michael@0: ['crash-handling']) michael@0: michael@0: # Passing parameters in the include section allows defining variables in michael@0: #the submodule scope: michael@0: self.assertEqual(parser.get('name', tags=['red']), michael@0: ['flowers']) michael@0: michael@0: # However, this should be overridable from the DEFAULT section in the michael@0: # included file and that overridable via the key directly connected to michael@0: # the test: michael@0: self.assertEqual(parser.get(name='flowers')[0]['blue'], michael@0: 'ocean') michael@0: self.assertEqual(parser.get(name='flowers')[0]['yellow'], michael@0: 'submarine') michael@0: michael@0: # You can query multiple times if you need to: michael@0: flowers = parser.get(foo='bar') michael@0: self.assertEqual(len(flowers), 2) michael@0: michael@0: # Using the inverse flag should invert the set of tests returned: michael@0: self.assertEqual(parser.get('name', inverse=True, tags=['red']), michael@0: ['crash-handling', 'fleem']) michael@0: michael@0: # All of the included tests actually exist: michael@0: self.assertEqual([i['name'] for i in parser.missing()], []) michael@0: michael@0: # Write the output to a manifest: michael@0: buffer = StringIO() michael@0: parser.write(fp=buffer, global_kwargs={'foo': 'bar'}) michael@0: self.assertEqual(buffer.getvalue().strip(), michael@0: '[DEFAULT]\nfoo = bar\n\n[fleem]\nsubsuite = \n\n[include/flowers]\nblue = ocean\nred = roses\nsubsuite = \nyellow = submarine') michael@0: michael@0: def test_copy(self): michael@0: """Test our ability to copy a set of manifests""" michael@0: michael@0: tempdir = tempfile.mkdtemp() michael@0: include_example = os.path.join(here, 'include-example.ini') michael@0: manifest = ManifestParser(manifests=(include_example,)) michael@0: manifest.copy(tempdir) michael@0: self.assertEqual(sorted(os.listdir(tempdir)), michael@0: ['fleem', 'include', 'include-example.ini']) michael@0: self.assertEqual(sorted(os.listdir(os.path.join(tempdir, 'include'))), michael@0: ['bar.ini', 'crash-handling', 'flowers', 'foo.ini']) michael@0: from_manifest = ManifestParser(manifests=(include_example,)) michael@0: to_manifest = os.path.join(tempdir, 'include-example.ini') michael@0: to_manifest = ManifestParser(manifests=(to_manifest,)) michael@0: self.assertEqual(to_manifest.get('name'), from_manifest.get('name')) michael@0: shutil.rmtree(tempdir) michael@0: michael@0: def test_path_override(self): michael@0: """You can override the path in the section too. michael@0: This shows that you can use a relative path""" michael@0: path_example = os.path.join(here, 'path-example.ini') michael@0: manifest = ManifestParser(manifests=(path_example,)) michael@0: self.assertEqual(manifest.tests[0]['path'], michael@0: os.path.join(here, 'fleem')) michael@0: michael@0: def test_relative_path(self): michael@0: """ michael@0: Relative test paths are correctly calculated. michael@0: """ michael@0: relative_path = os.path.join(here, 'relative-path.ini') michael@0: manifest = ManifestParser(manifests=(relative_path,)) michael@0: self.assertEqual(manifest.tests[0]['path'], michael@0: os.path.join(os.path.dirname(here), 'fleem')) michael@0: self.assertEqual(manifest.tests[0]['relpath'], michael@0: os.path.join('..', 'fleem')) michael@0: self.assertEqual(manifest.tests[1]['relpath'], michael@0: os.path.join('..', 'testsSIBLING', 'example')) michael@0: michael@0: def test_path_from_fd(self): michael@0: """ michael@0: Test paths are left untouched when manifest is a file-like object. michael@0: """ michael@0: fp = StringIO("[section]\npath=fleem") michael@0: manifest = ManifestParser(manifests=(fp,)) michael@0: self.assertEqual(manifest.tests[0]['path'], 'fleem') michael@0: self.assertEqual(manifest.tests[0]['relpath'], 'fleem') michael@0: self.assertEqual(manifest.tests[0]['manifest'], None) michael@0: michael@0: def test_comments(self): michael@0: """ michael@0: ensure comments work, see michael@0: https://bugzilla.mozilla.org/show_bug.cgi?id=813674 michael@0: """ michael@0: comment_example = os.path.join(here, 'comment-example.ini') michael@0: manifest = ManifestParser(manifests=(comment_example,)) michael@0: self.assertEqual(len(manifest.tests), 8) michael@0: names = [i['name'] for i in manifest.tests] michael@0: self.assertFalse('test_0202_app_launch_apply_update_dirlocked.js' in names) michael@0: michael@0: def test_verifyDirectory(self): michael@0: michael@0: directory = os.path.join(here, 'verifyDirectory') michael@0: michael@0: # correct manifest michael@0: manifest_path = os.path.join(directory, 'verifyDirectory.ini') michael@0: manifest = ManifestParser(manifests=(manifest_path,)) michael@0: missing = manifest.verifyDirectory(directory, extensions=('.js',)) michael@0: self.assertEqual(missing, (set(), set())) michael@0: michael@0: # manifest is missing test_1.js michael@0: test_1 = os.path.join(directory, 'test_1.js') michael@0: manifest_path = os.path.join(directory, 'verifyDirectory_incomplete.ini') michael@0: manifest = ManifestParser(manifests=(manifest_path,)) michael@0: missing = manifest.verifyDirectory(directory, extensions=('.js',)) michael@0: self.assertEqual(missing, (set(), set([test_1]))) michael@0: michael@0: # filesystem is missing test_notappearinginthisfilm.js michael@0: missing_test = os.path.join(directory, 'test_notappearinginthisfilm.js') michael@0: manifest_path = os.path.join(directory, 'verifyDirectory_toocomplete.ini') michael@0: manifest = ManifestParser(manifests=(manifest_path,)) michael@0: missing = manifest.verifyDirectory(directory, extensions=('.js',)) michael@0: self.assertEqual(missing, (set([missing_test]), set())) michael@0: michael@0: def test_just_defaults(self): michael@0: """Ensure a manifest with just a DEFAULT section exposes that data.""" michael@0: michael@0: parser = ManifestParser() michael@0: manifest = os.path.join(here, 'just-defaults.ini') michael@0: parser.read(manifest) michael@0: self.assertEqual(len(parser.tests), 0) michael@0: self.assertTrue(manifest in parser.manifest_defaults) michael@0: self.assertEquals(parser.manifest_defaults[manifest]['foo'], 'bar') michael@0: michael@0: def test_manifest_list(self): michael@0: """ michael@0: Ensure a manifest with just a DEFAULT section still returns michael@0: itself from the manifests() method. michael@0: """ michael@0: michael@0: parser = ManifestParser() michael@0: manifest = os.path.join(here, 'no-tests.ini') michael@0: parser.read(manifest) michael@0: self.assertEqual(len(parser.tests), 0) michael@0: self.assertTrue(len(parser.manifests()) == 1) michael@0: michael@0: if __name__ == '__main__': michael@0: unittest.main()