1#!/usr/bin/env python3
2#
3#   Copyright 2016 - The Android Open Source Project
4#
5#   Licensed under the Apache License, Version 2.0 (the "License");
6#   you may not use this file except in compliance with the License.
7#   You may obtain a copy of the License at
8#
9#       http://www.apache.org/licenses/LICENSE-2.0
10#
11#   Unless required by applicable law or agreed to in writing, software
12#   distributed under the License is distributed on an "AS IS" BASIS,
13#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14#   See the License for the specific language governing permissions and
15#   limitations under the License.
16
17import os
18import re
19import sys
20import uuid
21
22if sys.version_info < (3, ):
23    import warnings
24
25    with warnings.catch_warnings():
26        warnings.filterwarnings('ignore', category=PendingDeprecationWarning)
27        import imp
28
29    import importlib
30    import unittest2 as unittest
31
32    def import_module(name, path):
33        return imp.load_source(name, path)
34
35    def import_acts():
36        return importlib.import_module('acts')
37else:
38    import importlib.machinery
39    import unittest
40
41    def import_module(name, path):
42        return importlib.machinery.SourceFileLoader(name, path).load_module()
43
44    def import_acts():
45        return importlib.import_module('acts')
46
47
48PY_FILE_REGEX = re.compile('.+\.py$')
49
50BLACKLIST = [
51    'acts/controllers/rohdeschwarz_lib/contest.py',
52    'acts/controllers/native.py',
53    'acts/controllers/native_android_device.py',
54    'acts/controllers/packet_sender.py',
55    'acts/test_utils/wifi/ota_chamber.py',
56    'acts/controllers/buds_lib/dev_utils/proto/gen/nanopb_pb2.py',
57    'acts/test_utils/wifi/wifi_performance_test_utils.py',
58    'acts/test_utils/wifi/wifi_power_test_utils.py',
59    'acts/test_utils/wifi/wifi_retail_ap.py',
60    'acts/test_utils/bt/bt_power_test_utils.py',
61    'acts/test_utils/coex/coex_test_utils.py',
62    'acts/test_utils/tel/twilio_client.py',
63    'acts/test_utils/bt/A2dpBaseTest.py',
64    'acts/test_utils/bt/BtSarBaseTest.py',
65    'tests/google/ble/beacon_tests/BeaconSwarmTest.py',
66    'tests/google/bt/pts/BtCmdLineTest.py',
67    'tests/google/bt/headphone_automation/SineWaveQualityTest.py',
68    'tests/google/bt/audio_lab/BtChameleonTest.py',
69    'tests/google/native/bt/BtNativeTest.py',
70    'tests/google/wifi/WifiRvrTest.py',
71    'tests/google/wifi/WifiStaApConcurrencyStressTest.py',
72    'tests/google/wifi/WifiPasspointTest.py',
73    'tests/google/wifi/WifiOtaTest.py',
74    'tests/google/wifi/WifiRoamingPerformanceTest.py',
75    'tests/google/wifi/WifiRssiTest.py',
76    'tests/google/wifi/WifiPerformancePreflightTest.py',
77    'tests/google/wifi/WifiPingTest.py',
78    'tests/google/wifi/WifiThroughputStabilityTest.py',
79    'tests/google/wifi/WifiSensitivityTest.py',
80    'tests/google/wifi/WifiSoftApPerformanceTest.py',
81    'tests/google/tel/live/TelLiveMobilityStressTest.py',
82    'tests/google/tel/live/TelLiveNoSimTest.py',
83    'tests/google/tel/live/TelLiveLockedSimTest.py',
84    'tests/google/tel/live/TelLiveEmergencyTest.py',
85    'tests/google/tel/live/TelLiveConnectivityMonitorTest.py',
86    'tests/google/tel/live/TelLiveConnectivityMonitorMobilityTest.py',
87    'acts/test_utils/gnss/gnss_testlog_utils.py',
88]
89
90BLACKLIST_DIRECTORIES = [
91    'acts/controllers/buds_lib',
92    'acts/test_utils/audio_analysis_lib/',
93    'acts/test_utils/coex/',
94    'acts/test_utils/power/',
95    'tests/google/coex/',
96    'tests/google/gnss/',
97    'tests/google/power/',
98    'tests/google/bt/performance/',
99    'tests/google/bt/sar/',
100    'tests/google/fuchsia/'
101]
102
103BANNED_IMPORTS = ['mobly.controllers']
104
105
106class ActsImportUnitTest(unittest.TestCase):
107    """Test that all acts framework imports work."""
108
109    def test_import_acts_successful(self):
110        """Test that importing ACTS works."""
111        acts = import_acts()
112        self.assertIsNotNone(acts)
113
114    def test_import_framework_and_tests_successful(self):
115        """Dynamically test all imports from the framework and ACTS tests.
116        Ensure that no imports of banned packages/modules took place."""
117        acts = import_acts()
118        if hasattr(acts, '__path__') and len(acts.__path__) > 0:
119            acts_path = acts.__path__[0]
120        else:
121            acts_path = os.path.dirname(acts.__file__)
122        tests_path = os.path.normpath(os.path.join(acts_path, '../../tests'))
123
124        for base_dir in [acts_path, tests_path]:
125            for root, _, files in os.walk(base_dir):
126                for f in files:
127                    full_path = os.path.join(root, f)
128                    if (any(full_path.endswith(e) for e in BLACKLIST)
129                            or any(e in full_path
130                                   for e in BLACKLIST_DIRECTORIES)):
131                        continue
132
133                    path = os.path.relpath(os.path.join(root, f), os.getcwd())
134
135                    if PY_FILE_REGEX.match(full_path):
136                        with self.subTest(msg='import %s' % path):
137                            fake_module_name = str(uuid.uuid4())
138                            module = import_module(fake_module_name, path)
139                            self.assertIsNotNone(module)
140
141        # Suppress verbose output on assertion failure.
142        self.longMessage = False
143
144        for banned_import in BANNED_IMPORTS:
145            self.assertNotIn(
146                banned_import, sys.modules,
147                'Attempted to import the banned package/module '
148                '%s.' % banned_import)
149
150
151if __name__ == '__main__':
152    unittest.main()
153