1from pathlib import Path 2 3import pytest 4 5from genpinctrl import ( 6 validate_config_entry, 7 format_mode, 8 format_mode_f1, 9 format_remap, 10 format_remap_name, 11 get_gpio_ip_afs, 12 get_mcu_signals, 13 main, 14) 15 16 17def test_validate_config_entry(): 18 """Check that config entries are validated correctly""" 19 20 # no name 21 entry = {} 22 with pytest.raises(ValueError): 23 validate_config_entry(entry, "") 24 25 # no match 26 entry = {"name": "TEST"} 27 with pytest.raises(ValueError): 28 validate_config_entry(entry, "") 29 30 # no mode: F1 error only 31 entry = {"name": "TEST", "match": "TEST"} 32 with pytest.raises(ValueError): 33 validate_config_entry(entry, "STM32F1") 34 35 # invalid mode 36 entry = {"name": "TEST", "match": "TEST"} 37 entry["mode"] = "INVALID" 38 with pytest.raises(ValueError): 39 validate_config_entry(entry, "STM32F0") 40 with pytest.raises(ValueError): 41 validate_config_entry(entry, "STM32F1") 42 43 # valid modes 44 entry = {"name": "TEST", "match": "TEST"} 45 entry["mode"] = "analog" 46 validate_config_entry(entry, "STM32F0") 47 validate_config_entry(entry, "STM32F1") 48 entry["mode"] = "alternate" 49 validate_config_entry(entry, "STM32F0") 50 validate_config_entry(entry, "STM32F1") 51 entry["mode"] = "input" 52 validate_config_entry(entry, "STM32F1") 53 54 # invalid bias 55 entry = {"name": "TEST", "match": "TEST", "mode": "alternate"} 56 entry["bias"] = "INVALID" 57 with pytest.raises(ValueError): 58 validate_config_entry(entry, "STM32F0") 59 60 entry["bias"] = "pull-up" 61 with pytest.raises(ValueError): 62 validate_config_entry(entry, "STM32F1") 63 64 # valid bias 65 entry = {"name": "TEST", "match": "TEST"} 66 entry["bias"] = "disable" 67 entry["mode"] = "alternate" 68 validate_config_entry(entry, "STM32F0") 69 validate_config_entry(entry, "STM32F1") 70 entry["mode"] = "input" 71 validate_config_entry(entry, "STM32F1") 72 73 entry["bias"] = "pull-up" 74 entry["mode"] = "alternate" 75 validate_config_entry(entry, "STM32F0") 76 entry["mode"] = "input" 77 validate_config_entry(entry, "STM32F1") 78 79 entry["bias"] = "pull-down" 80 entry["mode"] = "alternate" 81 validate_config_entry(entry, "STM32F0") 82 entry["mode"] = "input" 83 validate_config_entry(entry, "STM32F1") 84 85 # invalid drive 86 entry = {"name": "TEST", "match": "TEST", "mode": "alternate"} 87 entry["drive"] = "INVALID" 88 with pytest.raises(ValueError): 89 validate_config_entry(entry, "STM32F0") 90 91 # valid drive 92 entry = {"name": "TEST", "match": "TEST", "mode": "alternate"} 93 entry["drive"] = "push-pull" 94 validate_config_entry(entry, "STM32F0") 95 entry["bias"] = "open-drain" 96 97 # invalid slew-rate 98 entry = {"name": "TEST", "match": "TEST", "mode": "alternate"} 99 entry["slew-rate"] = "INVALID" 100 with pytest.raises(ValueError): 101 validate_config_entry(entry, "STM32F0") 102 with pytest.raises(ValueError): 103 validate_config_entry(entry, "STM32F1") 104 105 # valid slew-rate 106 entry = {"name": "TEST", "match": "TEST", "mode": "alternate"} 107 entry["slew-rate"] = "low-speed" 108 validate_config_entry(entry, "STM32F0") 109 entry["slew-rate"] = "medium-speed" 110 validate_config_entry(entry, "STM32F0") 111 entry["slew-rate"] = "high-speed" 112 validate_config_entry(entry, "STM32F0") 113 entry["slew-rate"] = "very-high-speed" 114 validate_config_entry(entry, "STM32F0") 115 116 entry["slew-rate"] = "max-speed-10mhz" 117 validate_config_entry(entry, "STM32F1") 118 entry["slew-rate"] = "max-speed-2mhz" 119 validate_config_entry(entry, "STM32F1") 120 entry["slew-rate"] = "max-speed-50mhz" 121 validate_config_entry(entry, "STM32F1") 122 123 124def test_format_mode(): 125 """Test that format_mode works.""" 126 127 assert format_mode("analog", None) == "ANALOG" 128 assert format_mode("alternate", 0) == "AF0" 129 130 with pytest.raises(ValueError): 131 format_mode("INVALID", 0) 132 133 134def test_format_mode_f1(): 135 """Test that format_mode_f1 works.""" 136 137 assert format_mode_f1("analog") == "ANALOG" 138 assert format_mode_f1("input") == "GPIO_IN" 139 assert format_mode_f1("alternate") == "ALTERNATE" 140 141 with pytest.raises(ValueError): 142 format_mode_f1("INVALID") 143 144 145def test_format_remap(): 146 """Test that format_remap works.""" 147 148 assert format_remap("UART1_REMAP1") == "UART1_REMAP1" 149 assert format_remap(0) == "NO_REMAP" 150 assert format_remap(None) == "NO_REMAP" 151 152 153def test_format_remap_name(): 154 """Test that format_remap_name works.""" 155 156 assert format_remap_name("UART1_REMAP3") == "_remap3" 157 assert format_remap_name("UART1_REMAP2") == "_remap2" 158 assert format_remap_name("UART1_REMAP1") == "_remap1" 159 assert format_remap_name("UART1_REMAP0") == "" 160 assert format_remap_name(None) == "" 161 162 163def test_get_gpio_ip_afs(pindata): 164 """Test that IP AF files part of test STM32 Open Pin Data files are parsed 165 correctly. 166 """ 167 168 afs = get_gpio_ip_afs(pindata) 169 assert afs == { 170 "STM32F0TESTIP": { 171 "PA0": { 172 "UART1_TX": 0, 173 "UART1_RX": 1, 174 } 175 }, 176 "STM32F1TESTIP": { 177 "PA0": { 178 "UART1_TX": ["UART1_REMAP0", 179 "UART1_REMAP1", 180 "UART1_REMAP2", 181 "UART1_REMAP3"], 182 "UART1_RX": ["UART1_REMAP1"], 183 } 184 }, 185 } 186 187 188def test_get_mcu_signals(pindata): 189 """Test that MCU files part of test STM32 Open Pin Data are parsed correctly.""" 190 191 afs = get_gpio_ip_afs(pindata) 192 signals = get_mcu_signals(pindata, afs) 193 assert signals == { 194 "STM32F0": [ 195 { 196 "name": "STM32F0TESTDIE", 197 "pins": [ 198 { 199 "port": "a", 200 "pin": 0, 201 "mod": "", 202 "signals": [ 203 {"name": "UART1_TX", "af": 0}, 204 {"name": "UART1_RX", "af": 1}, 205 {"name": "ADC1_IN0", "af": None}, 206 ], 207 }, 208 ], 209 }, 210 ], 211 "STM32F1": [ 212 { 213 "name": "STM32F1TESTDIE", 214 "pins": [ 215 { 216 "port": "a", 217 "pin": 0, 218 "mod": "", 219 "signals": [ 220 {"name": "UART1_TX", "af": "UART1_REMAP0"}, 221 {"name": "UART1_TX", "af": "UART1_REMAP1"}, 222 {"name": "UART1_TX", "af": "UART1_REMAP2"}, 223 {"name": "UART1_TX", "af": "UART1_REMAP3"}, 224 {"name": "UART1_RX", "af": "UART1_REMAP1"}, 225 {"name": "ADC1_IN0", "af": 0}, 226 {"name": "I2C2_SCL", "af": 0}, 227 ], 228 }, 229 ], 230 }, 231 ], 232 } 233 234 235def test_folders_missing(): 236 """Test that missing STM32 Open Pin Data folders is handled correctly by 237 parsing functions. 238 """ 239 240 with pytest.raises(FileNotFoundError): 241 get_gpio_ip_afs(Path("MISSING_PATH")) 242 243 with pytest.raises(FileNotFoundError): 244 get_mcu_signals(Path("MISSING_PATH"), dict()) 245 246 247def test_main(data, pindata, tmp_path, mocker): 248 """Test that DTS files are generated correctly.""" 249 250 mocker.patch("genpinctrl.check_output", return_value=b"TEST") 251 252 main(pindata, tmp_path) 253 254 # check readme file 255 ref_readme_file = data / "README.rst" 256 gen_readme_file = tmp_path / "README.rst" 257 258 assert gen_readme_file.exists() 259 260 with open(ref_readme_file) as ref, open(gen_readme_file) as gen: 261 assert ref.read() == gen.read() 262 263 # check f0 file 264 ref_pinctrl_file = data / "stm32f0testdie-pinctrl.dtsi" 265 gen_pinctrl_file = tmp_path / "st" / "f0" / "stm32f0testdie-pinctrl.dtsi" 266 267 assert gen_pinctrl_file.exists() 268 269 with open(ref_pinctrl_file) as ref, open(gen_pinctrl_file) as gen: 270 assert ref.read() == gen.read() 271 272 # check f1 file 273 ref_pinctrl_file = data / "stm32f1testdie-pinctrl.dtsi" 274 gen_pinctrl_file = tmp_path / "st" / "f1" / "stm32f1testdie-pinctrl.dtsi" 275 276 assert gen_pinctrl_file.exists() 277 278 with open(ref_pinctrl_file) as ref, open(gen_pinctrl_file) as gen: 279 assert ref.read() == gen.read() 280