1818import pytest
1919from git import Repo
2020from pathlib import Path
21+ import tempfile
22+ import requests
23+ import zipfile
24+ import io
25+ import re
26+
27+
28+ # Util function to download library from URL
29+ def download_lib (url , download_dir ):
30+ tmp = Path (tempfile .TemporaryDirectory ().name )
31+ tmp .mkdir (parents = True , exist_ok = True )
32+ regex = re .compile (r"^(.*)-[0-9]+.[0-9]+.[0-9]" )
33+ response = requests .get (url )
34+ # Download and unzips library removing version suffix
35+ with zipfile .ZipFile (io .BytesIO (response .content )) as thezip :
36+ for zipinfo in thezip .infolist ():
37+ with thezip .open (zipinfo ) as f :
38+ dest_dir = tmp / regex .sub ("\\ g<1>" , zipinfo .filename )
39+ if zipinfo .is_dir ():
40+ dest_dir .mkdir (parents = True , exist_ok = True )
41+ else :
42+ dest_dir .write_bytes (f .read ())
43+
44+ # Recreates zip with folder without version suffix
45+ z = zipfile .ZipFile (download_dir , "w" )
46+ for f in tmp .glob ("**/*" ):
47+ z .write (f , arcname = f .relative_to (tmp ))
48+ z .close ()
2149
2250
2351def test_list (run_command ):
@@ -252,8 +280,12 @@ def test_install_git_url_and_zip_path_flags_visibility(run_command, data_dir, do
252280 assert res .failed
253281 assert "--git-url and --zip-path are disabled by default, for more information see:" in res .stderr
254282
255- assert run_command ("lib download AudioZero@1.0.0" )
256- zip_path = Path (downloads_dir , "libraries" , "AudioZero-1.0.0.zip" )
283+ # Download library
284+ url = "https://github.com/arduino-libraries/AudioZero/archive/refs/tags/1.1.1.zip"
285+ zip_path = Path (downloads_dir , "libraries" , "AudioZero.zip" )
286+ zip_path .parent .mkdir (parents = True , exist_ok = True )
287+ download_lib (url , zip_path )
288+
257289 res = run_command (f"lib install --zip-path { zip_path } " )
258290 assert res .failed
259291 assert "--git-url and --zip-path are disabled by default, for more information see:" in res .stderr
@@ -330,13 +362,16 @@ def test_install_with_zip_path(run_command, data_dir, downloads_dir):
330362 assert run_command ("config init --dest-dir ." , custom_env = env )
331363
332364 # Download a specific lib version
333- assert run_command ("lib download AudioZero@1.0.0" )
365+ # Download library
366+ url = "https://github.com/arduino-libraries/AudioZero/archive/refs/tags/1.1.1.zip"
367+ zip_path = Path (downloads_dir , "libraries" , "AudioZero.zip" )
368+ zip_path .parent .mkdir (parents = True , exist_ok = True )
369+ download_lib (url , zip_path )
334370
335- lib_install_dir = Path (data_dir , "libraries" , "AudioZero-1.0.0 " )
371+ lib_install_dir = Path (data_dir , "libraries" , "AudioZero" )
336372 # Verifies library is not already installed
337373 assert not lib_install_dir .exists ()
338374
339- zip_path = Path (downloads_dir , "libraries" , "AudioZero-1.0.0.zip" )
340375 # Test zip-path install
341376 res = run_command (f"lib install --zip-path { zip_path } " )
342377 assert res .ok
@@ -688,13 +723,14 @@ def test_install_with_zip_path_multiple_libraries(run_command, downloads_dir, da
688723 }
689724
690725 # Downloads zip to be installed later
691- assert run_command ("lib download WiFi101@0.16.1" )
692- assert run_command ("lib download ArduinoBLE@1.1.3" )
693726 wifi_zip_path = Path (downloads_dir , "libraries" , "WiFi101-0.16.1.zip" )
694727 ble_zip_path = Path (downloads_dir , "libraries" , "ArduinoBLE-1.1.3.zip" )
728+ download_lib ("https://github.com/arduino-libraries/WiFi101/archive/refs/tags/0.16.1.zip" , wifi_zip_path )
729+ download_lib ("https://github.com/arduino-libraries/ArduinoBLE/archive/refs/tags/1.1.3.zip" , ble_zip_path )
730+
731+ wifi_install_dir = Path (data_dir , "libraries" , "WiFi101" )
732+ ble_install_dir = Path (data_dir , "libraries" , "ArduinoBLE" )
695733
696- wifi_install_dir = Path (data_dir , "libraries" , "WiFi101-0.16.1" )
697- ble_install_dir = Path (data_dir , "libraries" , "ArduinoBLE-1.1.3" )
698734 # Verifies libraries are not installed
699735 assert not wifi_install_dir .exists ()
700736 assert not ble_install_dir .exists ()
@@ -860,6 +896,7 @@ def test_install_zip_lib_with_macos_metadata(run_command, data_dir, downloads_di
860896 assert lib_install_dir .exists ()
861897 files = list (lib_install_dir .glob ("**/*" ))
862898 assert lib_install_dir / "library.properties" in files
899+ assert lib_install_dir / "src" / "fake-lib.h" in files
863900
864901 # Reinstall library
865902 assert run_command (f"lib install --zip-path { zip_path } " )
@@ -868,3 +905,81 @@ def test_install_zip_lib_with_macos_metadata(run_command, data_dir, downloads_di
868905 assert lib_install_dir .exists ()
869906 files = list (lib_install_dir .glob ("**/*" ))
870907 assert lib_install_dir / "library.properties" in files
908+ assert lib_install_dir / "src" / "fake-lib.h" in files
909+
910+
911+ def test_install_zip_invalid_library (run_command , data_dir , downloads_dir ):
912+ # Initialize configs to enable --zip-path flag
913+ env = {
914+ "ARDUINO_DATA_DIR" : data_dir ,
915+ "ARDUINO_DOWNLOADS_DIR" : downloads_dir ,
916+ "ARDUINO_SKETCHBOOK_DIR" : data_dir ,
917+ "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL" : "true" ,
918+ }
919+ assert run_command ("config init --dest-dir ." , custom_env = env )
920+
921+ lib_install_dir = Path (data_dir , "libraries" , "lib-without-header" )
922+ # Verifies library is not already installed
923+ assert not lib_install_dir .exists ()
924+
925+ zip_path = Path (__file__ ).parent / "testdata" / "lib-without-header.zip"
926+ # Test zip-path install
927+ res = run_command (f"lib install --zip-path { zip_path } " )
928+ assert res .failed
929+ assert 'library is not valid: missing header file "lib-without-header.h"' in res .stderr
930+
931+ lib_install_dir = Path (data_dir , "libraries" , "lib-without-properties" )
932+ # Verifies library is not already installed
933+ assert not lib_install_dir .exists ()
934+
935+ zip_path = Path (__file__ ).parent / "testdata" / "lib-without-properties.zip"
936+ # Test zip-path install
937+ res = run_command (f"lib install --zip-path { zip_path } " )
938+ assert res .failed
939+ assert 'library is not valid: missing file "library.properties"' in res .stderr
940+
941+
942+ def test_install_git_invalid_library (run_command , data_dir , downloads_dir ):
943+ # Initialize configs to enable --zip-path flag
944+ env = {
945+ "ARDUINO_DATA_DIR" : data_dir ,
946+ "ARDUINO_DOWNLOADS_DIR" : downloads_dir ,
947+ "ARDUINO_SKETCHBOOK_DIR" : data_dir ,
948+ "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL" : "true" ,
949+ }
950+ assert run_command ("config init --dest-dir ." , custom_env = env )
951+
952+ # Create fake library repository
953+ repo_dir = Path (data_dir , "lib-without-header" )
954+ with Repo .init (repo_dir ) as repo :
955+ lib_properties = Path (repo_dir , "library.properties" )
956+ lib_properties .touch ()
957+ repo .index .add ([str (lib_properties )])
958+ repo .index .commit ("First commit" )
959+
960+ lib_install_dir = Path (data_dir , "libraries" , "lib-without-header" )
961+ # Verifies library is not already installed
962+ assert not lib_install_dir .exists ()
963+
964+ res = run_command (f"lib install --git-url { repo_dir } " , custom_env = env )
965+ assert res .failed
966+ assert 'library is not valid: missing header file "lib-without-header.h"' in res .stderr
967+ assert not lib_install_dir .exists ()
968+
969+ # Create another fake library repository
970+ repo_dir = Path (data_dir , "lib-without-properties" )
971+ with Repo .init (repo_dir ) as repo :
972+ lib_header = Path (repo_dir , "src" , "lib-without-properties.h" )
973+ lib_header .parent .mkdir (parents = True , exist_ok = True )
974+ lib_header .touch ()
975+ repo .index .add ([str (lib_header )])
976+ repo .index .commit ("First commit" )
977+
978+ lib_install_dir = Path (data_dir , "libraries" , "lib-without-properties" )
979+ # Verifies library is not already installed
980+ assert not lib_install_dir .exists ()
981+
982+ res = run_command (f"lib install --git-url { repo_dir } " , custom_env = env )
983+ assert res .failed
984+ assert 'library is not valid: missing file "library.properties"' in res .stderr
985+ assert not lib_install_dir .exists ()
0 commit comments