diff --git a/tests/runner/plugins/dummy-installer.py b/tests/runner/plugins/dummy-installer.py new file mode 100644 index 0000000..33e2fb9 --- /dev/null +++ b/tests/runner/plugins/dummy-installer.py @@ -0,0 +1,61 @@ +# -*- encoding: utf-8 -*- + +from typing import Union, cast + +import mobase + + +class DummyInstaller(mobase.IPluginInstallerSimple): + def init(self, organizer: mobase.IOrganizer) -> bool: + return True + + def author(self) -> str: + return "" + + def name(self) -> str: + return "" + + def description(self) -> str: + return "" + + def version(self) -> mobase.VersionInfo: + return mobase.VersionInfo("0.0.0") + + def settings(self) -> list[mobase.PluginSetting]: + return [] + + def isManualInstaller(self) -> bool: + return False + + def priority(self) -> int: + return 10 + + def isArchiveSupported(self, tree: mobase.IFileTree) -> bool: + return tree.find("needed-file.txt") is not None + + def install( + self, + name: mobase.GuessedString, + tree: mobase.IFileTree, + version: str, + nexus_id: int, + ) -> Union[ + mobase.InstallResult, + mobase.IFileTree, + tuple[mobase.InstallResult, mobase.IFileTree, str, int], + ]: + if tree.find("needed-file.txt") is None: + return mobase.InstallResult.FAILED + + if tree.find("extra-file.txt"): + name.update("new name") + new_tree = tree.createOrphanTree() + new_tree.move(tree, "subtree") + cast(mobase.IFileTree, new_tree.find("subtree")).remove("extra-file.txt") + return new_tree + + return (mobase.InstallResult.NOT_ATTEMPTED, tree, "2.4.5", 33) + + +def createPlugin() -> mobase.IPlugin: + return DummyInstaller() diff --git a/tests/runner/test_installer.cpp b/tests/runner/test_installer.cpp new file mode 100644 index 0000000..0341d26 --- /dev/null +++ b/tests/runner/test_installer.cpp @@ -0,0 +1,137 @@ +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include "MockOrganizer.h" +#include "iplugininstallersimple.h" +#include "pythonrunner.h" + +#include + +using namespace MOBase; + +// filetree implementation for testing purpose +// +class DummyFileTree : public IFileTree { +public: + DummyFileTree(std::shared_ptr parent, QString name) + : FileTreeEntry(parent, name), IFileTree() + { + } + +protected: + std::shared_ptr makeDirectory(std::shared_ptr parent, + QString name) const override + { + return std::make_shared(parent, name); + } + + bool doPopulate(std::shared_ptr parent, + std::vector>& entries) const override + { + return true; + } + + std::shared_ptr doClone() const override + { + return std::make_shared(nullptr, name()); + } +}; + +TEST(IPluginInstaller, Simple) +{ + const auto plugins_folder = QString(std::getenv("PLUGIN_DIR")); + + std::unique_ptr runner(CreatePythonRunner()); + runner->initialize(); + + // load objects + const auto objects = runner->load(plugins_folder + "/dummy-installer.py"); + EXPECT_EQ(objects.size(), 1); + + // load the IPlugin + IPluginInstallerSimple* plugin = qobject_cast(objects[0]); + EXPECT_NE(plugin, nullptr); + + // basic tests + EXPECT_EQ(plugin->priority(), 10); + EXPECT_EQ(plugin->isManualInstaller(), false); + + GuessedValue name{"default name"}; + QString version = "1.0.0"; + int nexus_id = 12; + + // invalid tree + { + std::shared_ptr invalid_tree = + std::make_shared(nullptr, "root"); + invalid_tree->addFile("some file"); + invalid_tree->addDirectory("some directory")->addFile("some other file"); + EXPECT_EQ(plugin->isArchiveSupported(invalid_tree), false); + EXPECT_EQ(plugin->install(name, invalid_tree, version, nexus_id), + IPluginInstaller::RESULT_FAILED); + + // extra arguments stay the same + EXPECT_EQ(name, "default name"); + EXPECT_EQ(version, "1.0.0"); + EXPECT_EQ(nexus_id, 12); + } + + // valid simple tree + { + std::shared_ptr valid_tree = + std::make_shared(nullptr, "root"); + const auto initial_tree = valid_tree; + valid_tree->addFile("needed-file.txt"); + valid_tree->addFile("some file"); + valid_tree->addDirectory("some directory")->addFile("some other file"); + + // valid tree + EXPECT_EQ(plugin->isArchiveSupported(valid_tree), true); + EXPECT_EQ(plugin->install(name, valid_tree, version, nexus_id), + IPluginInstaller::RESULT_NOTATTEMPTED); + + // name is not modified + EXPECT_EQ(name, "default name"); + + // tree is not modified + EXPECT_EQ(valid_tree, initial_tree); + + // version and ID are modified + EXPECT_EQ(version, "2.4.5"); + EXPECT_EQ(nexus_id, 33); + } + + // "complex" tree + { + std::shared_ptr complex_tree = + std::make_shared(nullptr, "root"); + const auto initial_tree = complex_tree; + const auto needed_file = complex_tree->addFile("needed-file.txt"); + const auto extra_file = complex_tree->addFile("extra-file.txt"); + const auto some_file = complex_tree->addFile("some file"); + const auto some_directory = complex_tree->addDirectory("some directory"); + some_directory->addFile("some other file"); + + // valid tree + EXPECT_EQ(plugin->isArchiveSupported(complex_tree), true); + EXPECT_EQ(plugin->install(name, complex_tree, version, nexus_id), + IPluginInstaller::RESULT_SUCCESS); + + // name is modified + EXPECT_EQ(name, "new name"); + + // tree is modified + EXPECT_EQ(complex_tree->findDirectory("subtree")->find("needed-file.txt"), + needed_file); + EXPECT_EQ( + complex_tree->findDirectory("subtree")->findDirectory("extra-file.txt"), + nullptr); + EXPECT_EQ( + complex_tree->findDirectory("subtree")->findDirectory("some directory"), + some_directory); + + // version and ID are not modified (from previous call) + EXPECT_EQ(version, "2.4.5"); + EXPECT_EQ(nexus_id, 33); + } +}