summaryrefslogtreecommitdiffstats
path: root/xbmc/addons/test
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/addons/test')
-rw-r--r--xbmc/addons/test/CMakeLists.txt6
-rw-r--r--xbmc/addons/test/TestAddonBuilder.cpp54
-rw-r--r--xbmc/addons/test/TestAddonDatabase.cpp80
-rw-r--r--xbmc/addons/test/TestAddonInfoBuilder.cpp179
-rw-r--r--xbmc/addons/test/TestAddonVersion.cpp271
5 files changed, 590 insertions, 0 deletions
diff --git a/xbmc/addons/test/CMakeLists.txt b/xbmc/addons/test/CMakeLists.txt
new file mode 100644
index 0000000..3365972
--- /dev/null
+++ b/xbmc/addons/test/CMakeLists.txt
@@ -0,0 +1,6 @@
+set(SOURCES TestAddonBuilder.cpp
+ TestAddonDatabase.cpp
+ TestAddonInfoBuilder.cpp
+ TestAddonVersion.cpp)
+
+core_add_test_library(addons_test)
diff --git a/xbmc/addons/test/TestAddonBuilder.cpp b/xbmc/addons/test/TestAddonBuilder.cpp
new file mode 100644
index 0000000..08f6c6d
--- /dev/null
+++ b/xbmc/addons/test/TestAddonBuilder.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "addons/AddonBuilder.h"
+#include "addons/LanguageResource.h"
+#include "addons/addoninfo/AddonInfo.h"
+#include "addons/addoninfo/AddonInfoBuilder.h"
+#include "addons/addoninfo/AddonType.h"
+
+#include <gtest/gtest.h>
+
+using namespace ADDON;
+
+
+class TestAddonBuilder : public ::testing::Test
+{
+protected:
+ TestAddonBuilder() = default;
+};
+
+TEST_F(TestAddonBuilder, ShouldFailWhenEmpty)
+{
+ EXPECT_EQ(nullptr, CAddonBuilder::Generate(nullptr, AddonType::UNKNOWN));
+}
+
+TEST_F(TestAddonBuilder, ShouldBuildDependencyAddons)
+{
+ std::vector<DependencyInfo> deps;
+ deps.emplace_back("a", CAddonVersion("1.0.0"), CAddonVersion("1.0.10"), false);
+
+ CAddonInfoBuilderFromDB builder;
+ builder.SetId("aa");
+ builder.SetDependencies(deps);
+ CAddonType addonType(AddonType::UNKNOWN);
+ builder.SetExtensions(addonType);
+ AddonPtr addon = CAddonBuilder::Generate(builder.get(), AddonType::UNKNOWN);
+ EXPECT_EQ(deps, addon->GetDependencies());
+}
+
+TEST_F(TestAddonBuilder, ShouldReturnDerivedType)
+{
+ CAddonInfoBuilderFromDB builder;
+ builder.SetId("aa");
+ CAddonType addonType(AddonType::RESOURCE_LANGUAGE);
+ builder.SetExtensions(addonType);
+ auto addon = std::dynamic_pointer_cast<CLanguageResource>(
+ CAddonBuilder::Generate(builder.get(), AddonType::UNKNOWN));
+ EXPECT_NE(nullptr, addon);
+}
diff --git a/xbmc/addons/test/TestAddonDatabase.cpp b/xbmc/addons/test/TestAddonDatabase.cpp
new file mode 100644
index 0000000..d5557dc
--- /dev/null
+++ b/xbmc/addons/test/TestAddonDatabase.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2016-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "addons/AddonDatabase.h"
+#include "addons/addoninfo/AddonInfoBuilder.h"
+#include "filesystem/SpecialProtocol.h"
+#include "settings/AdvancedSettings.h"
+
+#include <set>
+#include <utility>
+
+#include <gtest/gtest.h>
+
+using namespace ADDON;
+
+
+class AddonDatabaseTest : public ::testing::Test
+{
+protected:
+ DatabaseSettings settings;
+ CAddonDatabase database;
+
+ void SetUp() override
+ {
+ settings.type = "sqlite3";
+ settings.name = "test";
+ settings.host = CSpecialProtocol::TranslatePath("special://temp/");
+
+ database.Connect("test", settings, true);
+
+ std::set<std::string> installed{"repository.a", "repository.b"};
+ database.SyncInstalled(installed, installed, std::set<std::string>());
+
+ std::vector<AddonInfoPtr> addons;
+ CreateAddon(addons, "foo.bar", "1.0.0");
+ database.SetRepoUpdateData("repository.a", {});
+ database.UpdateRepositoryContent("repository.a", CAddonVersion("1.0.0"), "test", addons);
+
+ addons.clear();
+ CreateAddon(addons, "foo.baz", "1.1.0");
+ database.SetRepoUpdateData("repository.b", {});
+ database.UpdateRepositoryContent("repository.b", CAddonVersion("1.0.0"), "test", addons);
+ }
+
+ void CreateAddon(std::vector<AddonInfoPtr>& addons, std::string id, const std::string& version)
+ {
+ CAddonInfoBuilderFromDB builder;
+ builder.SetId(std::move(id));
+ builder.SetVersion(CAddonVersion(version));
+ addons.push_back(builder.get());
+ }
+
+ void TearDown() override
+ {
+ database.Close();
+ }
+};
+
+
+TEST_F(AddonDatabaseTest, TestFindById)
+{
+ VECADDONS addons;
+ EXPECT_TRUE(database.FindByAddonId("foo.baz", addons));
+ EXPECT_EQ(1U, addons.size());
+ EXPECT_EQ(addons.at(0)->ID(), "foo.baz");
+ EXPECT_EQ(addons.at(0)->Version().asString(), "1.1.0");
+ EXPECT_EQ(addons.at(0)->Origin(), "repository.b");
+}
+
+TEST_F(AddonDatabaseTest, TestFindByNonExistingId)
+{
+ VECADDONS addons;
+ EXPECT_TRUE(database.FindByAddonId("does.not.exist", addons));
+ EXPECT_EQ(0U, addons.size());
+}
diff --git a/xbmc/addons/test/TestAddonInfoBuilder.cpp b/xbmc/addons/test/TestAddonInfoBuilder.cpp
new file mode 100644
index 0000000..294d930
--- /dev/null
+++ b/xbmc/addons/test/TestAddonInfoBuilder.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2016-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "addons/Repository.h"
+#include "addons/addoninfo/AddonInfo.h"
+#include "addons/addoninfo/AddonInfoBuilder.h"
+#include "addons/addoninfo/AddonType.h"
+#include "utils/XBMCTinyXML.h"
+
+#include <set>
+
+#include <gtest/gtest.h>
+
+using namespace ADDON;
+
+const std::string addonXML = R"xml(
+<addon id="metadata.blablabla.org"
+ name="The Bla Bla Bla Addon"
+ version="1.2.3"
+ provider-name="Team Kodi">
+ <requires>
+ <import addon="xbmc.metadata" version="2.1.0"/>
+ <import addon="metadata.common.imdb.com" minversion="2.9.2" version="2.9.2"/>
+ <import addon="metadata.common.themoviedb.org" minversion="3.1.0" version="3.1.0"/>
+ <import addon="plugin.video.youtube" minversion="4.4.0" version="4.4.10" optional="true"/>
+ </requires>
+ <extension point="xbmc.metadata.scraper.movies"
+ language="en"
+ library="blablabla.xml"/>
+ <extension point="xbmc.python.module"
+ library="lib.so"/>
+ <extension point="kodi.addon.metadata">
+ <summary lang="en">Summary bla bla bla</summary>
+ <description lang="en">Description bla bla bla</description>
+ <disclaimer lang="en">Disclaimer bla bla bla</disclaimer>
+ <platform>all</platform>
+ <language>marsian</language>
+ <license>GPL v2.0</license>
+ <forum>https://forum.kodi.tv</forum>
+ <website>https://kodi.tv</website>
+ <email>a@a.dummy</email>
+ <source>https://github.com/xbmc/xbmc</source>
+ </extension>
+</addon>
+)xml";
+
+class TestAddonInfoBuilder : public ::testing::Test
+{
+protected:
+ TestAddonInfoBuilder() = default;
+};
+
+TEST_F(TestAddonInfoBuilder, ShouldFailWhenIdIsNotSet)
+{
+ AddonInfoPtr addon = CAddonInfoBuilder::Generate("", AddonType::UNKNOWN);
+ EXPECT_EQ(nullptr, addon);
+}
+
+TEST_F(TestAddonInfoBuilder, TestGenerate_Id_Type)
+{
+ AddonInfoPtr addon = CAddonInfoBuilder::Generate("foo.baz", AddonType::VISUALIZATION);
+ EXPECT_NE(nullptr, addon);
+ EXPECT_EQ(addon->ID(), "foo.baz");
+ EXPECT_EQ(addon->MainType(), AddonType::VISUALIZATION);
+ EXPECT_TRUE(addon->HasType(AddonType::VISUALIZATION));
+ EXPECT_FALSE(addon->HasType(AddonType::SCREENSAVER));
+}
+
+TEST_F(TestAddonInfoBuilder, TestGenerate_Repo)
+{
+ CXBMCTinyXML doc;
+ EXPECT_TRUE(doc.Parse(addonXML));
+ ASSERT_NE(nullptr, doc.RootElement());
+
+ RepositoryDirInfo repo;
+ AddonInfoPtr addon = CAddonInfoBuilder::Generate(doc.RootElement(), repo);
+ ASSERT_NE(nullptr, addon);
+ EXPECT_EQ(addon->ID(), "metadata.blablabla.org");
+
+ EXPECT_EQ(addon->MainType(), AddonType::SCRAPER_MOVIES);
+ EXPECT_TRUE(addon->HasType(AddonType::SCRAPER_MOVIES));
+ EXPECT_EQ(addon->Type(AddonType::SCRAPER_MOVIES)->LibName(), "blablabla.xml");
+ EXPECT_EQ(addon->Type(AddonType::SCRAPER_MOVIES)->GetValue("@language").asString(), "en");
+
+ EXPECT_TRUE(addon->HasType(AddonType::SCRIPT_MODULE));
+ EXPECT_EQ(addon->Type(AddonType::SCRIPT_MODULE)->LibName(), "lib.so");
+ EXPECT_FALSE(addon->HasType(AddonType::SCRAPER_ARTISTS));
+
+ EXPECT_EQ(addon->Name(), "The Bla Bla Bla Addon");
+ EXPECT_EQ(addon->Author(), "Team Kodi");
+ EXPECT_EQ(addon->Version().asString(), "1.2.3");
+
+ EXPECT_EQ(addon->Summary(), "Summary bla bla bla");
+ EXPECT_EQ(addon->Description(), "Description bla bla bla");
+ EXPECT_EQ(addon->Disclaimer(), "Disclaimer bla bla bla");
+ EXPECT_EQ(addon->License(), "GPL v2.0");
+ EXPECT_EQ(addon->Forum(), "https://forum.kodi.tv");
+ EXPECT_EQ(addon->Website(), "https://kodi.tv");
+ EXPECT_EQ(addon->EMail(), "a@a.dummy");
+ EXPECT_EQ(addon->Source(), "https://github.com/xbmc/xbmc");
+
+ const std::vector<DependencyInfo>& dependencies = addon->GetDependencies();
+ ASSERT_EQ(dependencies.size(), (long unsigned int)4);
+ EXPECT_EQ(dependencies[0].id, "xbmc.metadata");
+ EXPECT_EQ(dependencies[0].optional, false);
+ EXPECT_EQ(dependencies[0].versionMin.asString(), "2.1.0");
+ EXPECT_EQ(dependencies[0].version.asString(), "2.1.0");
+ EXPECT_EQ(dependencies[1].id, "metadata.common.imdb.com");
+ EXPECT_EQ(dependencies[1].optional, false);
+ EXPECT_EQ(dependencies[1].versionMin.asString(), "2.9.2");
+ EXPECT_EQ(dependencies[1].version.asString(), "2.9.2");
+ EXPECT_EQ(dependencies[2].id, "metadata.common.themoviedb.org");
+ EXPECT_EQ(dependencies[2].optional, false);
+ EXPECT_EQ(dependencies[2].versionMin.asString(), "3.1.0");
+ EXPECT_EQ(dependencies[2].version.asString(), "3.1.0");
+ EXPECT_EQ(dependencies[3].id, "plugin.video.youtube");
+ EXPECT_EQ(dependencies[3].optional, true);
+ EXPECT_EQ(dependencies[3].versionMin.asString(), "4.4.0");
+ EXPECT_EQ(dependencies[3].version.asString(), "4.4.10");
+
+ auto info = addon->ExtraInfo().find("language");
+ ASSERT_NE(info, addon->ExtraInfo().end());
+ EXPECT_EQ(info->second, "marsian");
+}
+
+TEST_F(TestAddonInfoBuilder, TestGenerate_DBEntry)
+{
+ CAddonInfoBuilderFromDB builder;
+ builder.SetId("video.blablabla.org");
+ builder.SetVersion(CAddonVersion("1.2.3"));
+ CAddonType addonType(AddonType::PLUGIN);
+ addonType.Insert("provides", "video audio");
+ builder.SetExtensions(addonType);
+ builder.SetName("The Bla Bla Bla Addon");
+ builder.SetAuthor("Team Kodi");
+ builder.SetSummary("Summary bla bla bla");
+ builder.SetDescription("Description bla bla bla");
+ builder.SetDisclaimer("Disclaimer bla bla bla");
+ builder.SetLicense("GPL v2.0");
+ builder.SetForum("https://forum.kodi.tv");
+ builder.SetWebsite("https://kodi.tv");
+ builder.SetEMail("a@a.dummy");
+ builder.SetSource("https://github.com/xbmc/xbmc");
+ InfoMap extrainfo;
+ extrainfo["language"] = "marsian";
+ builder.SetExtrainfo(extrainfo);
+
+ AddonInfoPtr addon = builder.get();
+ ASSERT_NE(nullptr, addon);
+ EXPECT_EQ(addon->ID(), "video.blablabla.org");
+
+ EXPECT_EQ(addon->MainType(), AddonType::PLUGIN);
+ EXPECT_TRUE(addon->HasType(AddonType::PLUGIN));
+ EXPECT_TRUE(addon->HasType(AddonType::VIDEO));
+ EXPECT_TRUE(addon->HasType(AddonType::AUDIO));
+ EXPECT_FALSE(addon->HasType(AddonType::GAME));
+
+ EXPECT_EQ(addon->Name(), "The Bla Bla Bla Addon");
+ EXPECT_EQ(addon->Author(), "Team Kodi");
+ EXPECT_EQ(addon->Version().asString(), "1.2.3");
+
+ EXPECT_EQ(addon->Summary(), "Summary bla bla bla");
+ EXPECT_EQ(addon->Description(), "Description bla bla bla");
+ EXPECT_EQ(addon->Disclaimer(), "Disclaimer bla bla bla");
+ EXPECT_EQ(addon->License(), "GPL v2.0");
+ EXPECT_EQ(addon->Forum(), "https://forum.kodi.tv");
+ EXPECT_EQ(addon->Website(), "https://kodi.tv");
+ EXPECT_EQ(addon->EMail(), "a@a.dummy");
+ EXPECT_EQ(addon->Source(), "https://github.com/xbmc/xbmc");
+
+ auto info = addon->ExtraInfo().find("language");
+ ASSERT_NE(info, addon->ExtraInfo().end());
+ EXPECT_EQ(info->second, "marsian");
+}
diff --git a/xbmc/addons/test/TestAddonVersion.cpp b/xbmc/addons/test/TestAddonVersion.cpp
new file mode 100644
index 0000000..0397792
--- /dev/null
+++ b/xbmc/addons/test/TestAddonVersion.cpp
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "addons/AddonVersion.h"
+
+#include <gtest/gtest.h>
+
+using namespace ADDON;
+
+class TestAddonVersion : public testing::Test
+{
+public:
+ TestAddonVersion()
+ : v1_0("1.0"),
+ v1_00("1.00"),
+ v1_0_0("1.0.0"),
+ v1_1("1.1"),
+ v1_01("1.01"),
+ v1_0_1("1.0.1"),
+ e1_v1_0_0("1:1.0.0"),
+ e1_v1_0_1("1:1.0.1"),
+ e2_v1_0_0("2:1.0.0"),
+ e1_v1_0_0_r1("1:1.0.0-1"),
+ e1_v1_0_1_r1("1:1.0.1-1"),
+ e1_v1_0_0_r2("1:1.0.0-2"),
+ v1_0_0_beta("1.0.0~beta"),
+ v1_0_0_alpha("1.0.0~alpha"),
+ v1_0_0_alpha2("1.0.0~alpha2"),
+ v1_0_0_alpha3("1.0.0~alpha3"),
+ v1_0_0_alpha10("1.0.0~alpha10")
+ {
+ }
+
+ CAddonVersion v1_0;
+ CAddonVersion v1_00;
+ CAddonVersion v1_0_0;
+ CAddonVersion v1_1;
+ CAddonVersion v1_01;
+ CAddonVersion v1_0_1;
+ CAddonVersion e1_v1_0_0;
+ CAddonVersion e1_v1_0_1;
+ CAddonVersion e2_v1_0_0;
+ CAddonVersion e1_v1_0_0_r1;
+ CAddonVersion e1_v1_0_1_r1;
+ CAddonVersion e1_v1_0_0_r2;
+ CAddonVersion v1_0_0_beta;
+ CAddonVersion v1_0_0_alpha;
+ CAddonVersion v1_0_0_alpha2;
+ CAddonVersion v1_0_0_alpha3;
+ CAddonVersion v1_0_0_alpha10;
+};
+
+TEST_F(TestAddonVersion, Constructor)
+{
+ EXPECT_EQ(v1_0.Upstream(), "1.0");
+ EXPECT_EQ(v1_0.Epoch(), 0);
+ EXPECT_TRUE(v1_0.Revision().empty());
+
+ EXPECT_EQ(v1_00.Upstream(), "1.00");
+ EXPECT_EQ(v1_00.Epoch(), 0);
+ EXPECT_TRUE(v1_00.Revision().empty());
+
+ EXPECT_EQ(v1_0_0.Upstream(), "1.0.0");
+ EXPECT_EQ(v1_0_0.Epoch(), 0);
+ EXPECT_TRUE(v1_0_0.Revision().empty());
+
+ EXPECT_EQ(v1_1.Upstream(), "1.1");
+ EXPECT_EQ(v1_1.Epoch(), 0);
+ EXPECT_TRUE(v1_1.Revision().empty());
+
+ EXPECT_EQ(v1_01.Upstream(), "1.01");
+ EXPECT_EQ(v1_01.Epoch(), 0);
+ EXPECT_TRUE(v1_01.Revision().empty());
+
+ EXPECT_EQ(v1_0_1.Upstream(), "1.0.1");
+ EXPECT_EQ(v1_0_1.Epoch(), 0);
+ EXPECT_TRUE(v1_0_1.Revision().empty());
+
+ EXPECT_EQ(e1_v1_0_0.Upstream(), "1.0.0");
+ EXPECT_EQ(e1_v1_0_0.Epoch(), 1);
+ EXPECT_TRUE(e1_v1_0_0.Revision().empty());
+
+ EXPECT_EQ(e1_v1_0_1.Upstream(), "1.0.1");
+ EXPECT_EQ(e1_v1_0_1.Epoch(), 1);
+ EXPECT_TRUE(e1_v1_0_1.Revision().empty());
+
+ EXPECT_EQ(e2_v1_0_0.Upstream(), "1.0.0");
+ EXPECT_EQ(e2_v1_0_0.Epoch(), 2);
+ EXPECT_TRUE(e2_v1_0_0.Revision().empty());
+
+ EXPECT_EQ(e1_v1_0_0_r1.Upstream(), "1.0.0");
+ EXPECT_EQ(e1_v1_0_0_r1.Epoch(), 1);
+ EXPECT_EQ(e1_v1_0_0_r1.Revision(), "1");
+
+ EXPECT_EQ(e1_v1_0_1_r1.Upstream(), "1.0.1");
+ EXPECT_EQ(e1_v1_0_1_r1.Epoch(), 1);
+ EXPECT_EQ(e1_v1_0_1_r1.Revision(), "1");
+
+ EXPECT_EQ(e1_v1_0_0_r2.Upstream(), "1.0.0");
+ EXPECT_EQ(e1_v1_0_0_r2.Epoch(), 1);
+ EXPECT_EQ(e1_v1_0_0_r2.Revision(), "2");
+
+ EXPECT_EQ(v1_0_0_beta.Upstream(), "1.0.0~beta");
+ EXPECT_EQ(v1_0_0_beta.Epoch(), 0);
+ EXPECT_TRUE(v1_0_0_beta.Revision().empty());
+
+ EXPECT_EQ(v1_0_0_alpha.Upstream(), "1.0.0~alpha");
+ EXPECT_EQ(v1_0_0_alpha.Epoch(), 0);
+ EXPECT_TRUE(v1_0_0_alpha.Revision().empty());
+
+ EXPECT_EQ(v1_0_0_alpha2.Upstream(), "1.0.0~alpha2");
+ EXPECT_EQ(v1_0_0_alpha2.Epoch(), 0);
+ EXPECT_TRUE(v1_0_0_alpha2.Revision().empty());
+
+ EXPECT_EQ(v1_0_0_alpha3.Upstream(), "1.0.0~alpha3");
+ EXPECT_EQ(v1_0_0_alpha3.Epoch(), 0);
+ EXPECT_TRUE(v1_0_0_alpha3.Revision().empty());
+
+ EXPECT_EQ(v1_0_0_alpha10.Upstream(), "1.0.0~alpha10");
+ EXPECT_EQ(v1_0_0_alpha10.Epoch(), 0);
+ EXPECT_TRUE(v1_0_0_alpha10.Revision().empty());
+}
+
+TEST_F(TestAddonVersion, asString)
+{
+ EXPECT_EQ(v1_0.asString(), "1.0");
+ EXPECT_EQ(v1_00.asString(), "1.00");
+ EXPECT_EQ(v1_0_0.asString(), "1.0.0");
+ EXPECT_EQ(v1_1.asString(), "1.1");
+ EXPECT_EQ(v1_01.asString(), "1.01");
+ EXPECT_EQ(v1_0_1.asString(), "1.0.1");
+ EXPECT_EQ(e1_v1_0_0.asString(), "1:1.0.0");
+ EXPECT_EQ(e1_v1_0_1.asString(), "1:1.0.1");
+ EXPECT_EQ(e2_v1_0_0.asString(), "2:1.0.0");
+ EXPECT_EQ(e1_v1_0_0_r1.asString(), "1:1.0.0-1");
+ EXPECT_EQ(e1_v1_0_1_r1.asString(), "1:1.0.1-1");
+ EXPECT_EQ(e1_v1_0_0_r2.asString(), "1:1.0.0-2");
+ EXPECT_EQ(v1_0_0_beta.asString(), "1.0.0~beta");
+ EXPECT_EQ(v1_0_0_alpha.asString(), "1.0.0~alpha");
+ EXPECT_EQ(v1_0_0_alpha2.asString(), "1.0.0~alpha2");
+ EXPECT_EQ(v1_0_0_alpha3.asString(), "1.0.0~alpha3");
+ EXPECT_EQ(v1_0_0_alpha10.asString(), "1.0.0~alpha10");
+}
+
+TEST_F(TestAddonVersion, Equals)
+{
+ EXPECT_EQ(v1_0, CAddonVersion("1.0"));
+ EXPECT_EQ(v1_00, CAddonVersion("1.00"));
+ EXPECT_EQ(v1_0_0, CAddonVersion("1.0.0"));
+ EXPECT_EQ(v1_1, CAddonVersion("1.1"));
+ EXPECT_EQ(v1_01, CAddonVersion("1.01"));
+ EXPECT_EQ(v1_0_1, CAddonVersion("1.0.1"));
+ EXPECT_EQ(e1_v1_0_0, CAddonVersion("1:1.0.0"));
+ EXPECT_EQ(e1_v1_0_1, CAddonVersion("1:1.0.1"));
+ EXPECT_EQ(e2_v1_0_0, CAddonVersion("2:1.0.0"));
+ EXPECT_EQ(e1_v1_0_0_r1, CAddonVersion("1:1.0.0-1"));
+ EXPECT_EQ(e1_v1_0_1_r1, CAddonVersion("1:1.0.1-1"));
+ EXPECT_EQ(e1_v1_0_0_r2, CAddonVersion("1:1.0.0-2"));
+ EXPECT_EQ(v1_0_0_beta, CAddonVersion("1.0.0~beta"));
+ EXPECT_EQ(v1_0_0_alpha, CAddonVersion("1.0.0~alpha"));
+ EXPECT_EQ(v1_0_0_alpha2, CAddonVersion("1.0.0~alpha2"));
+ EXPECT_EQ(v1_0_0_alpha3, CAddonVersion("1.0.0~alpha3"));
+ EXPECT_EQ(v1_0_0_alpha10, CAddonVersion("1.0.0~alpha10"));
+}
+
+TEST_F(TestAddonVersion, LessThan)
+{
+ EXPECT_LT(v1_0, v1_0_0);
+ EXPECT_LT(v1_0, v1_1);
+ EXPECT_LT(v1_0, v1_01);
+ EXPECT_LT(v1_0, v1_0_1);
+
+ EXPECT_LT(v1_00, v1_0_0);
+ EXPECT_LT(v1_00, v1_1);
+ EXPECT_LT(v1_00, v1_01);
+ EXPECT_LT(v1_00, v1_0_1);
+
+ EXPECT_LT(v1_0_0, v1_1);
+ EXPECT_LT(v1_0_0, v1_01);
+ EXPECT_LT(v1_0_0, v1_0_1);
+
+ EXPECT_LT(v1_0_1, v1_01);
+ EXPECT_LT(v1_0_1, v1_1);
+
+ // epochs
+ EXPECT_LT(v1_0_0, e1_v1_0_0);
+ EXPECT_LT(v1_0_0, e1_v1_0_1);
+ EXPECT_LT(v1_0_0, e2_v1_0_0);
+ EXPECT_LT(v1_0_1, e1_v1_0_1);
+ EXPECT_LT(v1_0_1, e2_v1_0_0);
+
+ EXPECT_LT(e1_v1_0_0, e1_v1_0_1);
+ EXPECT_LT(e1_v1_0_0, e2_v1_0_0);
+ EXPECT_LT(e1_v1_0_1, e2_v1_0_0);
+
+ // revisions
+ EXPECT_LT(e1_v1_0_0, e1_v1_0_0_r1);
+ EXPECT_LT(e1_v1_0_0, e1_v1_0_1_r1);
+ EXPECT_LT(e1_v1_0_0, e1_v1_0_0_r2);
+ EXPECT_LT(e1_v1_0_1, e1_v1_0_1_r1);
+ EXPECT_LT(e1_v1_0_0_r1, e1_v1_0_1);
+ EXPECT_LT(e1_v1_0_0_r1, e1_v1_0_1_r1);
+ EXPECT_LT(e1_v1_0_0_r1, e1_v1_0_0_r2);
+ EXPECT_LT(e1_v1_0_0_r2, e1_v1_0_1);
+ EXPECT_LT(e1_v1_0_0_r2, e1_v1_0_1_r1);
+ EXPECT_LT(e1_v1_0_1_r1, e2_v1_0_0);
+
+ // alpha, beta
+ EXPECT_LT(v1_0_0_beta, v1_0_0);
+ EXPECT_LT(v1_0_0_alpha, v1_0_0);
+ EXPECT_LT(v1_0_0_alpha, v1_0_0_beta);
+ EXPECT_LT(v1_0_0_alpha, v1_0_0_alpha2);
+ EXPECT_LT(v1_0_0_alpha, v1_0_0_alpha3);
+ EXPECT_LT(v1_0_0_alpha, v1_0_0_alpha10);
+ EXPECT_LT(v1_0_0_alpha2, v1_0_0);
+ EXPECT_LT(v1_0_0_alpha2, v1_0_0_beta);
+ EXPECT_LT(v1_0_0_alpha2, v1_0_0_alpha3);
+ EXPECT_LT(v1_0_0_alpha2, v1_0_0_alpha10);
+ EXPECT_LT(v1_0_0_alpha3, v1_0_0);
+ EXPECT_LT(v1_0_0_alpha3, v1_0_0_beta);
+ EXPECT_LT(v1_0_0_alpha3, v1_0_0_alpha10);
+ EXPECT_LT(v1_0_0_alpha10, v1_0_0);
+ EXPECT_LT(v1_0_0_alpha10, v1_0_0_beta);
+
+ // pep-0440/local-version-identifiers
+ // ref: https://www.python.org/dev/peps/pep-0440/#local-version-identifiers
+ // Python addons use this kind of versioning particularly for script.module
+ // addons. The "same" version number may exist in different branches or
+ // targeting different kodi versions while keeping consistency with the
+ // upstream module version. The addon version available in upper repos
+ // (let's say matrix) must have a higher version than the one stored in
+ // lower branches (e.g. leia) so that users receive the addon update
+ // when upgrading kodi.
+ // So, for instance, we use version x.x.x or version x.x.x+kodiversion.r to
+ // refer to the same upstream version x.x.x of the module.
+ // Eg: script.module.foo-1.0.0 or script.module.foo-1.0.0+leia.1 for upstream
+ // module foo (version 1.0.0) available for leia; and
+ // script.module.foo-1.0.0+matrix.1 for upstream module foo (1.0.0) for matrix.
+ // In summary, 1.0.0 or 1.0.0+leia.1 must be < than 1.0.0+matrix.1
+ // tests below assure this won't get broken inadvertently
+ EXPECT_LT(CAddonVersion("1.0.0"), CAddonVersion("1.0.0+matrix.1"));
+ EXPECT_LT(CAddonVersion("1.0.0+leia.1"), CAddonVersion("1.0.0+matrix.1"));
+ EXPECT_LT(CAddonVersion("1.0.0+matrix.1"), CAddonVersion("1.0.0+matrix.2"));
+ EXPECT_LT(CAddonVersion("1.0.0+matrix.1"), CAddonVersion("1.0.1+matrix.1"));
+ EXPECT_LT(CAddonVersion("1.0.0+matrix.1"), CAddonVersion("1.1.0+matrix.1"));
+ EXPECT_LT(CAddonVersion("1.0.0+matrix.1"), CAddonVersion("2.0.0+matrix.1"));
+ EXPECT_LT(CAddonVersion("1.0.0+matrix.1"), CAddonVersion("1.0.0.1"));
+ EXPECT_LT(CAddonVersion("1.0.0+Leia.1"), CAddonVersion("1.0.0+matrix.1"));
+ EXPECT_LT(CAddonVersion("1.0.0+leia.1"), CAddonVersion("1.0.0+Matrix.1"));
+}
+
+TEST_F(TestAddonVersion, Equivalent)
+{
+ EXPECT_FALSE(v1_0 != v1_00);
+ EXPECT_FALSE(v1_0 < v1_00);
+ EXPECT_FALSE(v1_0 > v1_00);
+ EXPECT_TRUE(v1_0 == v1_00);
+
+ EXPECT_FALSE(v1_01 != v1_1);
+ EXPECT_FALSE(v1_01 < v1_1);
+ EXPECT_FALSE(v1_01 > v1_1);
+ EXPECT_TRUE(v1_01 == v1_1);
+
+ // pep-0440/local-version-identifiers
+ EXPECT_TRUE(CAddonVersion("1.0.0+leia.1") == CAddonVersion("1.0.0+Leia.1"));
+}