@@ -584,6 +584,10 @@ def register_operations(self) -> Dict[str, List[str]]:
584584 "pydantic" : ["pydantic" ],
585585}
586586
587+ _TEST_BUILD_OPTIONS_INSTALLATION = _agent_engines ._BUILD_OPTIONS_INSTALLATION
588+ _TEST_INSTALLATION_SUBDIR = _utils ._INSTALLATION_SUBDIR
589+ _TEST_INSTALLATION_SCRIPT_PATH = f"{ _TEST_INSTALLATION_SUBDIR } /install_package.sh"
590+
587591
588592def _create_empty_fake_package (package_name : str ) -> str :
589593 """Creates a temporary directory structure representing an empty fake Python package.
@@ -1146,6 +1150,47 @@ def test_create_agent_engine_with_env_vars_list(
11461150 retry = _TEST_RETRY ,
11471151 )
11481152
1153+ def test_create_agent_engine_with_build_options (
1154+ self ,
1155+ create_agent_engine_mock ,
1156+ cloud_storage_create_bucket_mock ,
1157+ tarfile_open_mock ,
1158+ cloudpickle_dump_mock ,
1159+ cloudpickle_load_mock ,
1160+ importlib_metadata_version_mock ,
1161+ get_agent_engine_mock ,
1162+ get_gca_resource_mock ,
1163+ ):
1164+
1165+ with mock .patch ("os.path.exists" , return_value = True ):
1166+ agent_engines .create (
1167+ self .test_agent ,
1168+ display_name = _TEST_AGENT_ENGINE_DISPLAY_NAME ,
1169+ extra_packages = [
1170+ _TEST_INSTALLATION_SCRIPT_PATH ,
1171+ ],
1172+ build_options = {
1173+ _TEST_BUILD_OPTIONS_INSTALLATION : [_TEST_INSTALLATION_SCRIPT_PATH ]
1174+ },
1175+ )
1176+ test_spec = types .ReasoningEngineSpec (
1177+ package_spec = _TEST_AGENT_ENGINE_PACKAGE_SPEC ,
1178+ agent_framework = _agent_engines ._DEFAULT_AGENT_FRAMEWORK ,
1179+ )
1180+ test_spec .class_methods .append (_TEST_AGENT_ENGINE_QUERY_SCHEMA )
1181+ create_agent_engine_mock .assert_called_with (
1182+ parent = _TEST_PARENT ,
1183+ reasoning_engine = types .ReasoningEngine (
1184+ display_name = _TEST_AGENT_ENGINE_DISPLAY_NAME ,
1185+ spec = test_spec ,
1186+ ),
1187+ )
1188+
1189+ get_agent_engine_mock .assert_called_with (
1190+ name = _TEST_AGENT_ENGINE_RESOURCE_NAME ,
1191+ retry = _TEST_RETRY ,
1192+ )
1193+
11491194 @pytest .mark .parametrize (
11501195 "test_case_name, test_engine_instance, expected_framework" ,
11511196 [
@@ -2788,8 +2833,8 @@ def test_update_agent_engine_with_no_updates(
27882833 ValueError ,
27892834 match = (
27902835 "At least one of `agent_engine`, `requirements`, "
2791- "`extra_packages`, `display_name`, `description`, or `env_vars` "
2792- "must be specified."
2836+ "`extra_packages`, `display_name`, `description`, "
2837+ "`env_vars`, or `build_options` must be specified."
27932838 ),
27942839 ):
27952840 test_agent_engine = _generate_agent_engine_to_update ()
@@ -3228,3 +3273,114 @@ def test_scan_with_explicit_ignore_modules(self):
32283273 "cloudpickle" : "3.0.0" ,
32293274 "pydantic" : "1.11.1" ,
32303275 }
3276+
3277+
3278+ class TestValidateInstallationScripts :
3279+ # pytest does not allow absl.testing.parameterized.named_parameters.
3280+ @pytest .mark .parametrize (
3281+ "name, script_paths, extra_packages" ,
3282+ [
3283+ (
3284+ "valid_script_in_subdir_and_extra_packages" ,
3285+ [f"{ _utils ._INSTALLATION_SUBDIR } /script.sh" ],
3286+ [f"{ _utils ._INSTALLATION_SUBDIR } /script.sh" ],
3287+ ),
3288+ (
3289+ "multiple_valid_scripts" ,
3290+ [
3291+ f"{ _utils ._INSTALLATION_SUBDIR } /script1.sh" ,
3292+ f"{ _utils ._INSTALLATION_SUBDIR } /script2.sh" ,
3293+ ],
3294+ [
3295+ f"{ _utils ._INSTALLATION_SUBDIR } /script1.sh" ,
3296+ f"{ _utils ._INSTALLATION_SUBDIR } /script2.sh" ,
3297+ ],
3298+ ),
3299+ ("empty_script_paths_and_extra_packages" , [], []),
3300+ ],
3301+ )
3302+ def test_validate_installation_scripts (self , name , script_paths , extra_packages ):
3303+ _utils .validate_installation_scripts_or_raise (
3304+ script_paths = script_paths , extra_packages = extra_packages
3305+ )
3306+
3307+ @pytest .mark .parametrize (
3308+ "name, script_paths, extra_packages, error_message" ,
3309+ [
3310+ (
3311+ "script_not_in_subdir" ,
3312+ ["script.sh" ],
3313+ ["script.sh" ],
3314+ (
3315+ f"Required installation script 'script.sh' is not under"
3316+ f" '{ _utils ._INSTALLATION_SUBDIR } '"
3317+ ),
3318+ ),
3319+ (
3320+ "script_not_in_extra_packages" ,
3321+ [f"{ _utils ._INSTALLATION_SUBDIR } /script.sh" ],
3322+ [],
3323+ (
3324+ "User-defined installation script "
3325+ f"'{ _utils ._INSTALLATION_SUBDIR } /script.sh'"
3326+ " does not exist in `extra_packages`"
3327+ ),
3328+ ),
3329+ (
3330+ "extra_package_in_subdir_but_not_script" ,
3331+ [],
3332+ [f"{ _utils ._INSTALLATION_SUBDIR } /script.sh" ],
3333+ (
3334+ f"Extra package '{ _utils ._INSTALLATION_SUBDIR } /script.sh' "
3335+ "is in the installation scripts subdirectory, but is not "
3336+ "specified as an installation script."
3337+ ),
3338+ ),
3339+ (
3340+ "one_valid_one_invalid_script_not_in_subdir" ,
3341+ [f"{ _utils ._INSTALLATION_SUBDIR } /script1.sh" , "script2.sh" ],
3342+ [f"{ _utils ._INSTALLATION_SUBDIR } /script1.sh" , "script2.sh" ],
3343+ (
3344+ f"Required installation script 'script2.sh' is not under"
3345+ f" '{ _utils ._INSTALLATION_SUBDIR } '"
3346+ ),
3347+ ),
3348+ (
3349+ "one_valid_one_invalid_script_not_in_extra_packages" ,
3350+ [
3351+ f"{ _utils ._INSTALLATION_SUBDIR } /script1.sh" ,
3352+ f"{ _utils ._INSTALLATION_SUBDIR } /script2.sh" ,
3353+ ],
3354+ [f"{ _utils ._INSTALLATION_SUBDIR } /script1.sh" ],
3355+ (
3356+ "User-defined installation script "
3357+ f"'{ _utils ._INSTALLATION_SUBDIR } /script2.sh' "
3358+ "does not exist in `extra_packages`"
3359+ ),
3360+ ),
3361+ (
3362+ "one_valid_one_invalid_extra_package_in_subdir" ,
3363+ [f"{ _utils ._INSTALLATION_SUBDIR } /script1.sh" ],
3364+ [
3365+ f"{ _utils ._INSTALLATION_SUBDIR } /script1.sh" ,
3366+ f"{ _utils ._INSTALLATION_SUBDIR } /script2.sh" ,
3367+ ],
3368+ (
3369+ f"Extra package '{ _utils ._INSTALLATION_SUBDIR } /script2.sh' "
3370+ "is in the installation scripts subdirectory, but is not "
3371+ "specified as an installation script."
3372+ ),
3373+ ),
3374+ ],
3375+ )
3376+ def test_validate_installation_scripts_raises_error (
3377+ self ,
3378+ name ,
3379+ script_paths ,
3380+ extra_packages ,
3381+ error_message ,
3382+ ):
3383+ with pytest .raises (ValueError , match = error_message ):
3384+ _utils .validate_installation_scripts_or_raise (
3385+ script_paths = script_paths , extra_packages = extra_packages
3386+ )
0 commit comments