1 #include "ContextTest.hpp"
2 
3 CPPUNIT_TEST_SUITE_REGISTRATION(ContextTest);
4 
5 #include "libdnf/dnf-context.hpp"
6 #include "libdnf/dnf-repo-loader.h"
7 #include "libdnf/sack/query.hpp"
8 #include "libdnf/nevra.hpp"
9 #include "libdnf/utils/File.hpp"
10 #include "libdnf/sack/packageset.hpp"
11 #include "libdnf/dnf-sack-private.hpp"
12 
13 #include <memory>
14 
15 
setUp()16 void ContextTest::setUp()
17 {
18     dnf_context_set_config_file_path("");
19     context = dnf_context_new();
20 }
21 
tearDown()22 void ContextTest::tearDown()
23 {
24     g_object_unref(context);
25 }
26 
27 // XXX: look into sharing assert_list_names in the future
pkglist_has_nevra(GPtrArray * pkglist,const char * nevra)28 static gboolean pkglist_has_nevra(GPtrArray *pkglist, const char *nevra)
29 {
30     for (guint i = 0; i < pkglist->len; i++) {
31         DnfPackage *pkg = static_cast<DnfPackage *>(pkglist->pdata[i]);
32         if (g_str_equal(dnf_package_get_nevra(pkg), nevra))
33             return TRUE;
34     }
35     return FALSE;
36 }
37 
testLoadModules()38 void ContextTest::testLoadModules()
39 {
40     GError *error = nullptr;
41 
42     /* set up local context */
43     // set releasever to avoid crashing on missing /etc/os-release in the test data
44     dnf_context_set_release_ver(context, "26");
45     dnf_context_set_arch(context, "x86_64");
46     constexpr auto install_root = TESTDATADIR "/modules/";
47     dnf_context_set_install_root(context, install_root);
48     g_autoptr(DnfLock) lock = dnf_lock_new();
49     dnf_lock_set_lock_dir(lock, "/tmp");
50     constexpr auto repos_dir = TESTDATADIR "/modules/yum.repos.d/";
51     dnf_context_set_repo_dir(context, repos_dir);
52     dnf_context_set_solv_dir(context, "/tmp");
53     auto ret = dnf_context_setup(context, nullptr, &error);
54     g_assert_no_error(error);
55     g_assert(ret);
56 
57     /* load local metadata repo */
58     DnfRepo *repo = dnf_repo_loader_get_repo_by_id(dnf_context_get_repo_loader(context), "test", &error);
59     g_assert_no_error(error);
60     g_assert(repo != nullptr);
61     g_assert_cmpint(dnf_repo_get_enabled(repo), ==, DNF_REPO_ENABLED_METADATA | DNF_REPO_ENABLED_PACKAGES);
62     g_assert_cmpint(dnf_repo_get_kind(repo), ==, DNF_REPO_KIND_LOCAL);
63 
64     DnfState *state = dnf_state_new();
65     dnf_repo_check(repo, G_MAXUINT, state, &error);
66     g_object_unref(state);
67 
68     // Setup platform to prevent logger critical message
69     dnf_context_set_platform_module(context, "platform:26");
70 
71     state = dnf_context_get_state(context);
72     dnf_context_setup_sack(context, state, &error);
73     g_assert_no_error(error);
74 
75     auto sack = dnf_context_get_sack(context);
76     auto moduleExcludes = std::unique_ptr<libdnf::PackageSet>(dnf_sack_get_module_excludes(sack));
77     CPPUNIT_ASSERT(moduleExcludes->size() != 0);
78 
79     libdnf::ModulePackageContainer * c = dnf_sack_get_module_container(sack);
80     std::vector<libdnf::ModulePackage *> packages = c->getModulePackages();
81     for(auto const& package: packages) {
82         if (package->getName() == "httpd"){
83             // disabled stream
84             if (package->getStream() == "2.2")
85                 sackHasNot(sack, package);
86             // default module:stream
87             if (package->getStream() == "2.4")
88                 sackHas(sack, package);
89         }
90     }
91 
92     {
93         libdnf::Query query{sack};
94         // no match with modular RPM $name -> keep
95         std::string nevra = "grub2-2.02-0.40.x86_64";
96         query.addFilter(HY_PKG_NEVRA_STRICT, HY_EQ, nevra.c_str());
97         auto packageSet = const_cast<libdnf::PackageSet *>(query.runSet());
98         CPPUNIT_ASSERT(dnf_packageset_count(packageSet) >= 1);
99         auto package = dnf_package_new(sack, packageSet->operator[](0));
100         CPPUNIT_ASSERT(dnf_package_get_nevra(package) == nevra);
101         g_object_unref(package);
102         query.clear();
103     }
104 
105     {
106         libdnf::Query query{sack};
107         // $name matches with modular RPM $name -> exclude
108         std::string nevra = "httpd-2.2.10-1.x86_64";
109         query.addFilter(HY_PKG_NEVRA_STRICT, HY_EQ, nevra.c_str());
110         auto packageSet = const_cast<libdnf::PackageSet *>(query.runSet());
111         CPPUNIT_ASSERT(dnf_packageset_count(packageSet) == 0);
112         query.clear();
113     }
114 
115     {
116         libdnf::Query query{sack};
117         // Provides: $name matches with modular RPM $name -> exclude
118         std::string nevra = "httpd-provides-name-3.0-1.x86_64";
119         query.addFilter(HY_PKG_NEVRA_STRICT, HY_EQ, nevra.c_str());
120         auto packageSet = const_cast<libdnf::PackageSet *>(query.runSet());
121         CPPUNIT_ASSERT(dnf_packageset_count(packageSet) == 0);
122         query.clear();
123     }
124 
125     {
126         libdnf::Query query{sack};
127         // Provides: $name = ... matches with modular RPM $name -> exclude
128         std::string nevra = "httpd-provides-name-version-release-3.0-1.x86_64";
129         query.addFilter(HY_PKG_NEVRA_STRICT, HY_EQ, nevra.c_str());
130         auto packageSet = const_cast<libdnf::PackageSet *>(query.runSet());
131         CPPUNIT_ASSERT(dnf_packageset_count(packageSet) == 0);
132         query.clear();
133     }
134 
135     // try to install a nonexistent module
136     const char *module_specs[] = {"nonexistent", NULL};
137     g_assert(!dnf_context_module_install(context, module_specs, &error));
138     g_assert(error);
139     g_assert(strstr(error->message, "Unable to resolve argument 'nonexistent'"));
140     g_clear_pointer(&error, g_error_free);
141 
142     // wrong stream
143     module_specs[0] = "httpd:nonexistent";
144     g_assert(!dnf_context_module_install(context, module_specs, &error));
145     g_assert(error);
146     g_assert(strstr(error->message, "Unable to resolve argument 'httpd:nonexistent'"));
147     g_clear_pointer(&error, g_error_free);
148 
149     // try to install non-existent profile
150     module_specs[0] = "httpd:2.4/nonexistent";
151     g_assert(!dnf_context_module_install(context, module_specs, &error));
152     g_assert(error);
153     g_assert(strstr(error->message, "No profile found matching 'nonexistent'"));
154     g_clear_pointer(&error, g_error_free);
155 
156     // disable all modules
157     g_assert(dnf_context_module_disable_all(context, &error));
158     g_assert_no_error(error);
159 
160     // installing a modular package should fail
161     g_assert(!dnf_context_install(context, "httpd-2.4.25-8.x86_64", &error));
162     g_assert(error);
163     g_assert(strstr(error->message, "No package matches 'httpd-2.4.25-8.x86_64'"));
164     g_clear_pointer(&error, g_error_free);
165 
166     // reset all modules
167     g_assert(dnf_context_reset_all_modules(context, sack, &error));
168     g_assert_no_error(error);
169 
170     // enable and install default profile from modulemd-defaults
171     module_specs[0] = "httpd:2.4";
172     g_assert(dnf_context_module_install(context, module_specs, &error));
173     g_assert_no_error(error);
174     HyGoal goal = dnf_context_get_goal(context);
175     g_assert_cmpint(hy_goal_run_flags(goal, DNF_NONE), ==, 0);
176     g_autoptr(GPtrArray) pkgs = hy_goal_list_installs(goal, &error);
177     g_assert_no_error(error);
178     g_assert(pkgs);
179     g_assert(pkglist_has_nevra(pkgs, "httpd-2.4.25-8.x86_64"));
180     g_assert(pkglist_has_nevra(pkgs, "libnghttp2-1.21.1-1.x86_64"));
181 
182     // Verify we can install the default stream from modulemd-defaults.
183     // This would fail with EnableMultipleStreamsException if it didn't match
184     // the 2.4 stream since we enabled the 2.4 stream just above.
185     module_specs[0] = "httpd";
186     g_assert(dnf_context_module_install(context, module_specs, &error));
187     g_assert_no_error(error);
188 }
189 
sackHas(DnfSack * sack,libdnf::ModulePackage * pkg) const190 void ContextTest::sackHas(DnfSack * sack, libdnf::ModulePackage * pkg) const
191 {
192     libdnf::Query query{sack};
193     auto artifacts = pkg->getArtifacts();
194     for(auto & artifact: artifacts) {
195         artifact = artifact.replace(artifact.find("-0:"), 3, "-");
196         query.addFilter(HY_PKG_NEVRA_STRICT, HY_EQ, artifact.c_str());
197 
198         auto packageSet = const_cast<libdnf::PackageSet *>(query.runSet());
199         CPPUNIT_ASSERT(dnf_packageset_count(packageSet) >= 1);
200         auto package = dnf_package_new(sack, packageSet->operator[](0));
201         CPPUNIT_ASSERT(dnf_package_get_nevra(package) == artifact);
202         g_object_unref(package);
203 
204         query.clear();
205 
206     }
207 }
208 
sackHasNot(DnfSack * sack,libdnf::ModulePackage * pkg) const209 void ContextTest::sackHasNot(DnfSack * sack, libdnf::ModulePackage * pkg) const
210 {
211     libdnf::Query query{sack};
212     auto artifacts = pkg->getArtifacts();
213     for(auto & artifact: artifacts) {
214         artifact = artifact.replace(artifact.find("-0:"), 3, "-");
215         query.addFilter(HY_PKG_NEVRA_STRICT, HY_EQ, artifact.c_str());
216 
217         auto packageSet = const_cast<libdnf::PackageSet *>(query.runSet());
218         CPPUNIT_ASSERT(dnf_packageset_count(packageSet) == 0);
219 
220         query.clear();
221     }
222 }
223