1#!/usr/bin/env python 2# 3# Copyright 2019 Espressif Systems (Shanghai) CO LTD 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 subprocess 19import sys 20import unittest 21 22try: 23 from StringIO import StringIO 24except ImportError: 25 from io import StringIO 26 27try: 28 import idf 29except ImportError: 30 sys.path.append('..') 31 import idf 32 33current_dir = os.path.dirname(os.path.realpath(__file__)) 34idf_py_path = os.path.join(current_dir, '..', 'idf.py') 35extension_path = os.path.join(current_dir, 'test_idf_extensions', 'test_ext') 36link_path = os.path.join(current_dir, '..', 'idf_py_actions', 'test_ext') 37 38 39class TestExtensions(unittest.TestCase): 40 def test_extension_loading(self): 41 try: 42 os.symlink(extension_path, link_path) 43 os.environ['IDF_EXTRA_ACTIONS_PATH'] = os.path.join(current_dir, 'extra_path') 44 output = subprocess.check_output([sys.executable, idf_py_path, '--help'], 45 env=os.environ).decode('utf-8', 'ignore') 46 47 self.assertIn('--test-extension-option', output) 48 self.assertIn('test_subcommand', output) 49 self.assertIn('--some-extension-option', output) 50 self.assertIn('extra_subcommand', output) 51 finally: 52 os.remove(link_path) 53 54 def test_extension_execution(self): 55 try: 56 os.symlink(extension_path, link_path) 57 os.environ['IDF_EXTRA_ACTIONS_PATH'] = ';'.join([os.path.join(current_dir, 'extra_path')]) 58 output = subprocess.check_output( 59 [sys.executable, idf_py_path, '--some-extension-option=awesome', 'test_subcommand', 'extra_subcommand'], 60 env=os.environ).decode('utf-8', 'ignore') 61 self.assertIn('!!! From some global callback: awesome', output) 62 self.assertIn('!!! From some subcommand', output) 63 self.assertIn('!!! From test global callback: test', output) 64 self.assertIn('!!! From some subcommand', output) 65 finally: 66 os.remove(link_path) 67 68 def test_hidden_commands(self): 69 try: 70 os.symlink(extension_path, link_path) 71 os.environ['IDF_EXTRA_ACTIONS_PATH'] = ';'.join([os.path.join(current_dir, 'extra_path')]) 72 output = subprocess.check_output([sys.executable, idf_py_path, '--help'], 73 env=os.environ).decode('utf-8', 'ignore') 74 self.assertIn('test_subcommand', output) 75 self.assertNotIn('hidden_one', output) 76 77 finally: 78 os.remove(link_path) 79 80 81class TestDependencyManagement(unittest.TestCase): 82 def test_dependencies(self): 83 result = idf.init_cli()( 84 args=['--dry-run', 'flash'], 85 standalone_mode=False, 86 ) 87 self.assertEqual(['flash'], list(result.keys())) 88 89 def test_order_only_dependencies(self): 90 result = idf.init_cli()( 91 args=['--dry-run', 'build', 'fullclean', 'all'], 92 standalone_mode=False, 93 ) 94 self.assertEqual(['fullclean', 'all'], list(result.keys())) 95 96 def test_repeated_dependencies(self): 97 result = idf.init_cli()( 98 args=['--dry-run', 'fullclean', 'app', 'fullclean', 'fullclean'], 99 standalone_mode=False, 100 ) 101 self.assertEqual(['fullclean', 'app'], list(result.keys())) 102 103 def test_complex_case(self): 104 result = idf.init_cli()( 105 args=['--dry-run', 'clean', 'monitor', 'clean', 'fullclean', 'flash'], 106 standalone_mode=False, 107 ) 108 self.assertEqual(['fullclean', 'clean', 'flash', 'monitor'], list(result.keys())) 109 110 def test_dupplicated_commands_warning(self): 111 capturedOutput = StringIO() 112 sys.stderr = capturedOutput 113 idf.init_cli()( 114 args=['--dry-run', 'clean', 'monitor', 'build', 'clean', 'fullclean', 'all'], 115 standalone_mode=False, 116 ) 117 sys.stderr = sys.__stderr__ 118 self.assertIn( 119 'WARNING: Commands "all", "clean" are found in the list of commands more than once.', 120 capturedOutput.getvalue()) 121 122 sys.stderr = capturedOutput 123 idf.init_cli()( 124 args=['--dry-run', 'clean', 'clean'], 125 standalone_mode=False, 126 ) 127 sys.stderr = sys.__stderr__ 128 self.assertIn( 129 'WARNING: Command "clean" is found in the list of commands more than once.', capturedOutput.getvalue()) 130 131 132class TestVerboseFlag(unittest.TestCase): 133 def test_verbose_messages(self): 134 output = subprocess.check_output( 135 [ 136 sys.executable, 137 idf_py_path, 138 '-C%s' % current_dir, 139 '-v', 140 'test-verbose', 141 ], env=os.environ).decode('utf-8', 'ignore') 142 143 self.assertIn('Verbose mode on', output) 144 145 def test_verbose_messages_not_shown_by_default(self): 146 output = subprocess.check_output( 147 [ 148 sys.executable, 149 idf_py_path, 150 '-C%s' % current_dir, 151 'test-verbose', 152 ], env=os.environ).decode('utf-8', 'ignore') 153 154 self.assertIn('Output from test-verbose', output) 155 self.assertNotIn('Verbose mode on', output) 156 157 158class TestGlobalAndSubcommandParameters(unittest.TestCase): 159 def test_set_twice_same_value(self): 160 """Can set -D twice: globally and for subcommand if values are the same""" 161 162 idf.init_cli()( 163 args=['--dry-run', '-DAAA=BBB', '-DCCC=EEE', 'build', '-DAAA=BBB', '-DCCC=EEE'], 164 standalone_mode=False, 165 ) 166 167 def test_set_twice_different_values(self): 168 """Cannot set -D twice: for command and subcommand of idf.py (with different values)""" 169 170 with self.assertRaises(idf.FatalError): 171 idf.init_cli()( 172 args=['--dry-run', '-DAAA=BBB', 'build', '-DAAA=EEE', '-DCCC=EEE'], 173 standalone_mode=False, 174 ) 175 176 177class TestDeprecations(unittest.TestCase): 178 def test_exit_with_error_for_subcommand(self): 179 try: 180 subprocess.check_output([sys.executable, idf_py_path, '-C%s' % current_dir, 'test-2'], env=os.environ, 181 stderr=subprocess.STDOUT) 182 except subprocess.CalledProcessError as e: 183 self.assertIn('Error: Command "test-2" is deprecated and was removed.', e.output.decode('utf-8', 'ignore')) 184 185 def test_exit_with_error_for_option(self): 186 try: 187 subprocess.check_output([sys.executable, idf_py_path, '-C%s' % current_dir, '--test-5=asdf'], 188 env=os.environ, stderr=subprocess.STDOUT) 189 except subprocess.CalledProcessError as e: 190 self.assertIn('Error: Option "test_5" is deprecated since v2.0 and was removed in v3.0.', 191 e.output.decode('utf-8', 'ignore')) 192 193 def test_deprecation_messages(self): 194 output = subprocess.check_output( 195 [ 196 sys.executable, 197 idf_py_path, 198 '-C%s' % current_dir, 199 '--test-0=a', 200 '--test-1=b', 201 '--test-2=c', 202 '--test-3=d', 203 'test-0', 204 '--test-sub-0=sa', 205 '--test-sub-1=sb', 206 'ta', 207 'test-1', 208 ], 209 env=os.environ, stderr=subprocess.STDOUT).decode('utf-8', 'ignore') 210 211 self.assertIn('Warning: Option "test_sub_1" is deprecated and will be removed in future versions.', output) 212 self.assertIn( 213 'Warning: Command "test-1" is deprecated and will be removed in future versions. ' 214 'Please use alternative command.', output) 215 self.assertIn('Warning: Option "test_1" is deprecated and will be removed in future versions.', output) 216 self.assertIn( 217 'Warning: Option "test_2" is deprecated and will be removed in future versions. ' 218 'Please update your parameters.', output) 219 self.assertIn('Warning: Option "test_3" is deprecated and will be removed in future versions.', output) 220 self.assertNotIn('"test-0" is deprecated', output) 221 self.assertNotIn('"test_0" is deprecated', output) 222 223 224if __name__ == '__main__': 225 unittest.main() 226