diff --git a/tools/src/test/python/dlpx/virtualization/_internal/commands/test_build.py b/tools/src/test/python/dlpx/virtualization/_internal/commands/test_build.py index a207b31e..a2077b33 100644 --- a/tools/src/test/python/dlpx/virtualization/_internal/commands/test_build.py +++ b/tools/src/test/python/dlpx/virtualization/_internal/commands/test_build.py @@ -697,3 +697,81 @@ def test_minimum_lua_version_parameter(plugin_config_content, src_dir, upload_artifact = build.prepare_upload_artifact( plugin_config_content, src_dir, schema_content, {}) assert expected == upload_artifact.get('minimumLuaVersion') + + @staticmethod + @pytest.mark.parametrize('build_number', ['1.0.1']) + def test_build_change_and_build_again(plugin_config_content, src_dir, + schema_content): + upload_artifact = build.prepare_upload_artifact( + plugin_config_content, src_dir, schema_content, {}) + assert plugin_config_content['buildNumber'] == upload_artifact['buildNumber'] + changed_build_number = '7.2.12' + changed_host_type = ['WINDOWS'] + plugin_config_content['buildNumber'] = changed_build_number + plugin_config_content['hostTypes'] = changed_host_type + upload_artifact_2 = build.prepare_upload_artifact( + plugin_config_content, src_dir, schema_content, {}) + assert changed_build_number == upload_artifact_2.get('buildNumber') + assert changed_host_type == upload_artifact_2.get('hostTypes') + + @staticmethod + @pytest.mark.parametrize('repository_definition', + [{ + 'type': 'object', + 'properties': { + 'name': { + 'type': 'badDataType' + } + }, + 'nameField': 'name', + 'identityFields': ['name'] + }]) + @mock.patch('dlpx.virtualization._internal.codegen.generate_python') + def test_bad_data_type_in_schema(mock_generate_python, + plugin_config_file, + artifact_file): + with pytest.raises(exceptions.UserError) as err_info: + build.build(plugin_config_file, artifact_file, False, False) + + message = err_info.value.message + exp_error = "'badDataType' is not valid under any of the given schemas" + assert exp_error in message + + assert not mock_generate_python.called + + @staticmethod + @pytest.mark.parametrize('host_types', ['']) + @mock.patch('dlpx.virtualization._internal.codegen.generate_python') + def test_empty_host_type(mock_generate_python, plugin_config_file, + artifact_file): + with pytest.raises(exceptions.UserError) as err_info: + build.build(plugin_config_file, artifact_file, False, False) + + message = err_info.value.message + assert "Validation failed" in message + assert not mock_generate_python.called + + @staticmethod + @pytest.mark.parametrize('plugin_name', ['']) + @mock.patch('dlpx.virtualization._internal.codegen.generate_python') + def test_empty_plugin_name(mock_generate_python, plugin_config_file, + artifact_file): + with pytest.raises(exceptions.UserError) as err_info: + build.build(plugin_config_file, artifact_file, False, False) + + message = err_info.value.message + assert "Validation failed" in message + assert not mock_generate_python.called + + @staticmethod + @mock.patch('os.path.isabs', return_value=False) + def test_non_existing_entry_file(mock_relative_path, plugin_config_file, + plugin_config_content, artifact_file): + entry_module, _ = plugin_config_content['entryPoint'].split(':') + + with pytest.raises(exceptions.UserError) as err_info: + build.build(plugin_config_file, artifact_file, False, False) + + message = err_info.value.message + exp_message = "No module named {module}".format(module=entry_module) + assert exp_message in message diff --git a/tools/src/test/python/dlpx/virtualization/_internal/commands/test_initialize.py b/tools/src/test/python/dlpx/virtualization/_internal/commands/test_initialize.py index 5486eaa6..62fa9dfe 100644 --- a/tools/src/test/python/dlpx/virtualization/_internal/commands/test_initialize.py +++ b/tools/src/test/python/dlpx/virtualization/_internal/commands/test_initialize.py @@ -114,6 +114,20 @@ def test_init(tmpdir, ingestion_strategy, host_type, schema_template, assert contents == format_entry_point_template( config['id'], ingestion_strategy, host_type) + @staticmethod + def test_init_with_relative_path(tmpdir): + os.chdir(tmpdir.strpath) + init.init(".", const.DIRECT_TYPE, "", const.UNIX_HOST_TYPE) + + result = plugin_util.validate_plugin_config_file( + os.path.join(tmpdir.strpath, init.DEFAULT_PLUGIN_CONFIG_FILE), + True) + + config = result.plugin_config_content + + # Validate that the plugin name is equal to plugin id + assert config['name'] == config['id'] + @staticmethod def test_init_without_plugin_name(tmpdir): init.init(tmpdir.strpath, const.DIRECT_TYPE, "", const.UNIX_HOST_TYPE) diff --git a/tools/src/test/python/dlpx/virtualization/_internal/fake_plugin/direct/bad_syntax.py b/tools/src/test/python/dlpx/virtualization/_internal/fake_plugin/direct/bad_syntax.py new file mode 100644 index 00000000..c0024806 --- /dev/null +++ b/tools/src/test/python/dlpx/virtualization/_internal/fake_plugin/direct/bad_syntax.py @@ -0,0 +1,17 @@ +# +# Copyright (c) 2020 by Delphix. All rights reserved. +# +# flake8: noqa +from dlpx.virtualization.platform import Plugin + +plugin = Plugin() + + +@plugin.discovery.repository() +def repository_discovery(source_connection) + return None + + +@plugin.discovery.source_config() +def source_config_discovery(source_connection, repository) + return None diff --git a/tools/src/test/python/dlpx/virtualization/_internal/fake_plugin/direct/import_error.py b/tools/src/test/python/dlpx/virtualization/_internal/fake_plugin/direct/import_error.py new file mode 100644 index 00000000..6ec26e2a --- /dev/null +++ b/tools/src/test/python/dlpx/virtualization/_internal/fake_plugin/direct/import_error.py @@ -0,0 +1,17 @@ +# +# Copyright (c) 2020 by Delphix. All rights reserved. +# +# flake8: noqa +from dlpxxx.virtualization.platform import Plugin + +plugin = Plugin() + + +@plugin.discovery.repository() +def repository_discovery(source_connection): + return None + + +@plugin.discovery.source_config() +def source_config_discovery(source_connection, repository): + return None diff --git a/tools/src/test/python/dlpx/virtualization/_internal/fake_plugin/direct/undefined_name.py b/tools/src/test/python/dlpx/virtualization/_internal/fake_plugin/direct/undefined_name.py new file mode 100644 index 00000000..db4ec97a --- /dev/null +++ b/tools/src/test/python/dlpx/virtualization/_internal/fake_plugin/direct/undefined_name.py @@ -0,0 +1,17 @@ +# +# Copyright (c) 2020 by Delphix. All rights reserved. +# +# flake8: noqa +from dlpx.virtualization.platform import Plugin + +plugin = Plugin() + + +@directplugin.discovery.repository() +def repository_discovery(source_connection): + return None + + +@plugin.discovery.source_config() +def source_config_discovery(source_connection, repository): + return None diff --git a/tools/src/test/python/dlpx/virtualization/_internal/test_cli.py b/tools/src/test/python/dlpx/virtualization/_internal/test_cli.py index f9a98dc7..9ef87f31 100644 --- a/tools/src/test/python/dlpx/virtualization/_internal/test_cli.py +++ b/tools/src/test/python/dlpx/virtualization/_internal/test_cli.py @@ -163,6 +163,39 @@ def test_invalid_ingestion_strategy(plugin_name): assert result.exit_code != 0 + @staticmethod + def test_blank_ingestion_strategy(plugin_name): + runner = click_testing.CliRunner() + + result = runner.invoke( + cli.delphix_sdk, + ['init', '-n', plugin_name, '-s', '']) + + assert result.exit_code != 0 + assert "invalid choice" in result.output + + @staticmethod + def test_non_existent_root_dir(plugin_name): + runner = click_testing.CliRunner() + + result = runner.invoke( + cli.delphix_sdk, + ['init', '-n', plugin_name, '-r', '/file/does/not/exist']) + + assert result.exit_code != 0 + assert "'/file/does/not/exist' does not exist" in result.output + + @staticmethod + def test_empty_root_dir(plugin_name): + runner = click_testing.CliRunner() + + result = runner.invoke( + cli.delphix_sdk, + ['init', '-n', plugin_name, '-r', '']) + + assert result.exit_code != 0 + assert "Invalid value for '-r'" in result.output + @staticmethod def test_name_required(): runner = click_testing.CliRunner() @@ -385,6 +418,35 @@ def test_with_dev_fail(mock_build, plugin_config_file, artifact_file, assert result.exit_code == 2 assert not mock_build.called, 'build should not have been called' + @staticmethod + @pytest.mark.parametrize('plugin_config_file', + ['']) + def test_empty_config_file(plugin_config_file): + runner = click_testing.CliRunner() + result = runner.invoke(cli.delphix_sdk, + ['build', '-c', plugin_config_file]) + + assert result.exit_code == 2 + expected_error_strings = ("Error: Invalid value for '-c'", + "is a directory") + for expected_error in expected_error_strings: + assert expected_error in result.output + + @staticmethod + @pytest.mark.parametrize('artifact_file', + ['']) + def test_empty_artifact_file(plugin_config_file, artifact_file): + runner = click_testing.CliRunner() + result = runner.invoke(cli.delphix_sdk, + ['build', '-c', plugin_config_file, + '-a', artifact_file]) + + assert result.exit_code == 2 + expected_error_strings = ("Error: Invalid value for '-a'", + "is a directory") + for expected_error in expected_error_strings: + assert expected_error in result.output + class TestUploadCli: @staticmethod diff --git a/tools/src/test/python/dlpx/virtualization/_internal/test_plugin_importer.py b/tools/src/test/python/dlpx/virtualization/_internal/test_plugin_importer.py index 7a1ce1ab..a8795765 100644 --- a/tools/src/test/python/dlpx/virtualization/_internal/test_plugin_importer.py +++ b/tools/src/test/python/dlpx/virtualization/_internal/test_plugin_importer.py @@ -244,3 +244,73 @@ def test_plugin_info_warn_mode(mock_import, mock_relative_path, plugin_config_content, False) except Exception: raise AssertionError() + + @staticmethod + @pytest.mark.parametrize( + 'entry_point,plugin_type,expected_errors', + [('successful:ne_symbol', 'DIRECT', [ + "Error: Entry point 'successful:ne_symbol' does not exist.", + "'ne_symbol' is not a symbol in module ", + ])]) + @mock.patch('dlpx.virtualization._internal.file_util.get_src_dir_path') + def test_non_existing_symbol_in_module(mock_file_util, plugin_config_file, + fake_src_dir, expected_errors): + mock_file_util.return_value = fake_src_dir + + with pytest.raises(exceptions.UserError) as err_info: + importer = get_plugin_importer(plugin_config_file) + importer.validate_plugin_module() + + message = err_info.value.message + for error in expected_errors: + assert error in message + + @staticmethod + @pytest.mark.parametrize( + 'entry_point,expected_error', + [('import_error:plugin', + "Error: No module named dlpxxx.virtualization.platform")]) + @mock.patch('dlpx.virtualization._internal.file_util.get_src_dir_path') + def test_import_error(mock_file_util, plugin_config_file, + fake_src_dir, expected_error): + mock_file_util.return_value = fake_src_dir + + with pytest.raises(exceptions.UserError) as err_info: + importer = get_plugin_importer(plugin_config_file) + importer.validate_plugin_module() + + message = err_info.value.message + assert expected_error in message + + @staticmethod + @pytest.mark.parametrize( + 'entry_point,expected_error', + [('bad_syntax:plugin', "SDK Error: invalid syntax")]) + @mock.patch('dlpx.virtualization._internal.file_util.get_src_dir_path') + def test_bad_syntax(mock_file_util, plugin_config_file, + fake_src_dir, expected_error): + mock_file_util.return_value = fake_src_dir + + with pytest.raises(exceptions.SDKToolingError) as err_info: + importer = get_plugin_importer(plugin_config_file) + importer.validate_plugin_module() + + message = err_info.value.message + assert expected_error in message + + @staticmethod + @pytest.mark.parametrize( + 'entry_point,expected_error', + [('undefined_name:plugin', + "SDK Error: name 'directplugin' is not defined")]) + @mock.patch('dlpx.virtualization._internal.file_util.get_src_dir_path') + def test_undefined_name_error(mock_file_util, plugin_config_file, + fake_src_dir, expected_error): + mock_file_util.return_value = fake_src_dir + + with pytest.raises(exceptions.SDKToolingError) as err_info: + importer = get_plugin_importer(plugin_config_file) + importer.validate_plugin_module() + + message = err_info.value.message + assert expected_error in message diff --git a/tools/src/test/python/dlpx/virtualization/_internal/test_plugin_validator.py b/tools/src/test/python/dlpx/virtualization/_internal/test_plugin_validator.py index 893e6e41..e81ce7da 100644 --- a/tools/src/test/python/dlpx/virtualization/_internal/test_plugin_validator.py +++ b/tools/src/test/python/dlpx/virtualization/_internal/test_plugin_validator.py @@ -118,6 +118,7 @@ def test_plugin_additional_properties(plugin_config_file, @staticmethod @pytest.mark.parametrize('host_types', [['xxx']]) @pytest.mark.parametrize('src_dir', [None]) + @pytest.mark.parametrize('plugin_type', ['INDIRECT']) def test_multiple_validation_errors(plugin_config_file, plugin_config_content): with pytest.raises(exceptions.SchemaValidationError) as err_info: @@ -128,6 +129,7 @@ def test_multiple_validation_errors(plugin_config_file, message = err_info.value.message assert "'srcDir' is a required property" in message assert "'xxx' is not one of ['UNIX', 'WINDOWS']" in message + assert "'INDIRECT' is not one of ['DIRECT', 'STAGED']" in message @staticmethod @mock.patch('os.path.isabs', return_value=False)