Skip to content

Commit

Permalink
Extend unit tests with user_cb_data in repo::DownloadCallbacks
Browse files Browse the repository at this point in the history
The `test_package_downloader` unit tests for C++, Python, Ruby, Perl now test
passing `user_cb_data`.
In the `test_repo` tests, the implementation of the `add_new_download` and
`progress` methods has been intentionally removed to test functionality in case
the library user does not implement these methods.
  • Loading branch information
jrohel authored and m-blaha committed Nov 18, 2024
1 parent 3b07d21 commit dabead7
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 104 deletions.
53 changes: 38 additions & 15 deletions test/libdnf5/repo/test_package_downloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
#include <libdnf5/repo/package_downloader.hpp>
#include <libdnf5/rpm/package_query.hpp>

#include <algorithm>
#include <filesystem>

CPPUNIT_TEST_SUITE_REGISTRATION(PackageDownloaderTest);
Expand All @@ -41,13 +42,15 @@ class DownloadCallbacks : public libdnf5::repo::DownloadCallbacks {
[[maybe_unused]] const char * description,
[[maybe_unused]] double total_to_download) override {
++add_new_download_cnt;
return nullptr;
std::string user_cb_data = std::string("Package: ") + description;
return user_cb_data_container.emplace_back(std::move(user_cb_data)).data();
}

int end([[maybe_unused]] void * user_cb_data, TransferStatus status, const char * msg) override {
++end_cnt;
end_status = status;
end_msg = libdnf5::utils::string::c_to_str(msg);
user_cb_data_array.emplace_back(static_cast<const char *>(user_cb_data));
end_status.emplace_back(status);
end_msg.emplace_back(libdnf5::utils::string::c_to_str(msg));
return 0;
}

Expand All @@ -68,41 +71,59 @@ class DownloadCallbacks : public libdnf5::repo::DownloadCallbacks {
return 0;
}

int add_new_download_cnt = 0;
int end_cnt = 0;
TransferStatus end_status = TransferStatus::ERROR;
std::string end_msg;
std::vector<std::string> user_cb_data_container;

int add_new_download_cnt = 0;
int progress_cnt = 0;
int mirror_failure_cnt = 0;
int end_cnt = 0;

std::vector<const char *> user_cb_data_array;
std::vector<TransferStatus> end_status;
std::vector<std::string> end_msg;
};

void PackageDownloaderTest::test_package_downloader() {
auto repo = add_repo_rpm("rpm-repo1");

libdnf5::rpm::PackageQuery query(base);
query.filter_name("one");
query.filter_version("2");
query.filter_arch("noarch");
CPPUNIT_ASSERT_EQUAL((size_t)1, query.size());
CPPUNIT_ASSERT_EQUAL((size_t)2, query.size());

auto downloader = libdnf5::repo::PackageDownloader(base);

auto cbs_unique_ptr = std::make_unique<DownloadCallbacks>();
auto cbs = cbs_unique_ptr.get();
base.set_download_callbacks(std::move(cbs_unique_ptr));

downloader.add(*query.begin());
for (const auto & package : query) {
downloader.add(package);
}

downloader.download();

CPPUNIT_ASSERT_EQUAL(1, cbs->add_new_download_cnt);
CPPUNIT_ASSERT_EQUAL(1, cbs->end_cnt);
CPPUNIT_ASSERT_EQUAL(DownloadCallbacks::TransferStatus::SUCCESSFUL, cbs->end_status);
CPPUNIT_ASSERT_EQUAL(std::string(""), cbs->end_msg);
std::sort(cbs->user_cb_data_container.begin(), cbs->user_cb_data_container.end());
CPPUNIT_ASSERT_EQUAL(
(std::vector<std::string>{"Package: one-0:1-1.noarch", "Package: one-0:2-1.noarch"}),
cbs->user_cb_data_container);

CPPUNIT_ASSERT_GREATEREQUAL(1, cbs->progress_cnt);
CPPUNIT_ASSERT_EQUAL(2, cbs->add_new_download_cnt);
CPPUNIT_ASSERT_EQUAL(2, cbs->end_cnt);
CPPUNIT_ASSERT_GREATEREQUAL(2, cbs->progress_cnt);
CPPUNIT_ASSERT_EQUAL(0, cbs->mirror_failure_cnt);

std::sort(cbs->user_cb_data_array.begin(), cbs->user_cb_data_array.end(), [](const char * a, const char * b) {
return std::string_view(a).compare(b) < 0;
});
CPPUNIT_ASSERT_EQUAL(cbs->user_cb_data_container[0].c_str(), cbs->user_cb_data_array[0]);
CPPUNIT_ASSERT_EQUAL(cbs->user_cb_data_container[1].c_str(), cbs->user_cb_data_array[1]);

CPPUNIT_ASSERT_EQUAL(
(std::vector<DownloadCallbacks::TransferStatus>{
DownloadCallbacks::TransferStatus::SUCCESSFUL, DownloadCallbacks::TransferStatus::SUCCESSFUL}),
cbs->end_status);
CPPUNIT_ASSERT_EQUAL((std::vector<std::string>{"", ""}), cbs->end_msg);
}

void PackageDownloaderTest::test_package_downloader_temp_files_memory() {
Expand Down Expand Up @@ -136,6 +157,8 @@ void PackageDownloaderTest::test_package_downloader_temp_files_memory() {

CPPUNIT_ASSERT_EQUAL(4, cbs->add_new_download_cnt);
CPPUNIT_ASSERT_EQUAL(4, cbs->end_cnt);
CPPUNIT_ASSERT_GREATEREQUAL(4, cbs->progress_cnt);
CPPUNIT_ASSERT_EQUAL(0, cbs->mirror_failure_cnt);

auto paths_prefix = std::filesystem::path(repo->get_cachedir()) / std::filesystem::path("packages");
const std::vector<std::string> expected = {
Expand Down
37 changes: 31 additions & 6 deletions test/perl5/libdnf5/repo/test_package_downloader.t
Original file line number Diff line number Diff line change
Expand Up @@ -31,28 +31,46 @@ use BaseTestCase;
sub new {
my $class = shift;
my $self = $class->SUPER::new(@_);
$self->{end_cnt} = 0;
$self->{user_cb_data_container} = [];
$self->{start_cnt} = 0;
$self->{progress_cnt} = 0;
$self->{mirror_failure_cnt} = 0;
$self->{end_cnt} = 0;
$self->{user_cb_data_array} = [];
$self->{end_status} = [];
$self->{end_msg} = [];
return bless($self, $class);
}

sub add_new_download {
my ($self, $user_data, $description, $total_to_download) = @_;
$self->{start_cnt}++;
my $user_cb_data = "Package: " . $description;
push(@{$self->{user_cb_data_container}}, $user_cb_data);
return scalar @{$self->{user_cb_data_container}} - 1;
}

sub end {
my ($self, $user_cb_data, $status, $error_message) = @_;
$self->{end_cnt}++;
::ok($user_cb_data>=0 && $user_cb_data<=1, "end: user_cb_data");
push @{$self->{user_cb_data_array}}, $user_cb_data;
push @{$self->{end_status}}, $status;
push @{$self->{end_msg}}, $error_message;
return 0;
}

sub progress {
my ($self, $user_cb_data, $total_to_download, $downloaded) = @_;
$self->{progress_cnt}++;
::ok($user_cb_data>=0 && $user_cb_data<=1, "progress: user_cb_data");
return 0;
}

sub mirror_failure {
my ($self, $user_cb_data, $msg, $url, $metadata) = @_;
my $self = shift;
$self->{mirror_failure_cnt}++;
::ok($user_cb_data>=0 && $user_cb_data<=1, "mirror_failure: user_cb_data");
return 0;
}
}
Expand All @@ -64,7 +82,7 @@ my $repo = $test->add_repo_rpm("rpm-repo1");
my $query = new libdnf5::rpm::PackageQuery($test->{base});
$query->filter_name(["one"]);
$query->filter_arch(["noarch"]);
is($query->size(), 2);
is($query->size(), 2, "number of packages in query");

my $downloader = new libdnf5::repo::PackageDownloader($test->{base});

Expand All @@ -81,8 +99,15 @@ $downloader->download();

$cbs = $test->{base}->get_download_callbacks();

is($cbs->{end_cnt}, 2);
ok($cbs->{progress_cnt} >= 2);
is($cbs->{mirror_failure_cnt}, 0);
is_deeply($cbs->{user_cb_data_container}, ["Package: one-0:1-1.noarch", "Package: one-0:2-1.noarch"]);

is($cbs->{start_cnt}, 2, "start_cnt");
is($cbs->{end_cnt}, 2, "end_cnt");
ok($cbs->{progress_cnt} >= 2, "progress_cnt");
is($cbs->{mirror_failure_cnt}, 0, "mirror_failure_cnt");

is_deeply($cbs->{user_cb_data_array}, [0, 1], "user_cb_data_array");
is_deeply($cbs->{end_status}, [$libdnf5::repo::DownloadCallbacks::TransferStatus_SUCCESSFUL, $libdnf5::repo::DownloadCallbacks::TransferStatus_SUCCESSFUL]);
is_deeply($cbs->{end_status}, [0, 0]);

done_testing();
74 changes: 50 additions & 24 deletions test/python3/libdnf5/repo/test_package_downloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,54 +25,80 @@

class TestPackageDownloader(base_test_case.BaseTestCase):
def test_package_downloader(self):
repo = self.add_repo_rpm("rpm-repo1")

query = libdnf5.rpm.PackageQuery(self.base)
query.filter_name(["one"])
query.filter_version(["2"])
query.filter_arch(["noarch"])
self.assertEqual(query.size(), 1)

downloader = libdnf5.repo.PackageDownloader(self.base)

class PackageDownloadCallbacks(libdnf5.repo.DownloadCallbacks):
end_cnt = 0
end_status = None
end_msg = None

progress_cnt = 0
mirror_failure_cnt = 0
test_instance = None

def __init__(self):
super(PackageDownloadCallbacks, self).__init__()
self.user_cb_data_container = [] # Hold references to user_cb_data
self.start_cnt = 0
self.progress_cnt = 0
self.mirror_failure_cnt = 0
self.end_cnt = 0
self.user_cb_data_array = []
self.end_status = []
self.end_msg = []

def add_new_download(self, user_data, description, total_to_download):
self.start_cnt += 1
user_cb_data_reference = "Package: " + description
self.user_cb_data_container.append(user_cb_data_reference)
return len(self.user_cb_data_container) - 1

def end(self, user_cb_data, status, msg):
self.end_cnt += 1
self.end_status = status
self.end_msg = msg
self.test_instance.assertIn(user_cb_data, [0, 1])
self.user_cb_data_array.append(user_cb_data)
self.end_status.append(status)
self.end_msg.append(msg)
return 0

def progress(self, user_cb_data, total_to_download, downloaded):
self.progress_cnt += 1
self.test_instance.assertIn(user_cb_data, [0, 1])
return 0

def mirror_failure(self, user_cb_data, msg, url):
self.mirror_failure_cnt += 1
self.test_instance.assertIn(user_cb_data, [0, 1])
return 0

PackageDownloadCallbacks.test_instance = self

repo = self.add_repo_rpm("rpm-repo1")

query = libdnf5.rpm.PackageQuery(self.base)
query.filter_name(["one"])
query.filter_arch(["noarch"])
self.assertEqual(query.size(), 2)

downloader = libdnf5.repo.PackageDownloader(self.base)

cbs = PackageDownloadCallbacks()
self.base.set_download_callbacks(
libdnf5.repo.DownloadCallbacksUniquePtr(cbs))

downloader.add(query.begin().value())
for package in query:
downloader.add(package)

downloader.download()

# forcefully deallocate the downloader, to check cbs is still valid
downloader = None
gc.collect()

self.assertEqual(cbs.end_cnt, 1)
self.assertEqual(
cbs.end_status, PackageDownloadCallbacks.TransferStatus_SUCCESSFUL)
self.assertEqual(cbs.end_msg, None)
cbs.user_cb_data_container.sort()
self.assertEqual(cbs.user_cb_data_container, [
"Package: one-0:1-1.noarch", "Package: one-0:2-1.noarch"])

self.assertGreaterEqual(cbs.progress_cnt, 1)
self.assertEqual(cbs.start_cnt, 2)
self.assertGreaterEqual(cbs.progress_cnt, 2)
self.assertEqual(cbs.mirror_failure_cnt, 0)
self.assertEqual(cbs.end_cnt, 2)

cbs.user_cb_data_array.sort()
self.assertEqual(cbs.user_cb_data_array, [0, 1])
self.assertEqual(
cbs.end_status,
[PackageDownloadCallbacks.TransferStatus_SUCCESSFUL, PackageDownloadCallbacks.TransferStatus_SUCCESSFUL])
self.assertEqual(cbs.end_msg, [None, None])
21 changes: 0 additions & 21 deletions test/python3/libdnf5/repo/test_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,17 @@

class TestRepo(base_test_case.BaseTestCase):
class DownloadCallbacks(libdnf5.repo.DownloadCallbacks):
start_cnt = 0
start_what = None

end_cnt = 0
end_error_message = None

progress_cnt = 0
fastest_mirror_cnt = 0
handle_mirror_failure_cnt = 0

def add_new_download(self, user_data, descr, total):
self.start_cnt += 1
self.start_what = descr
return None

def end(self, user_cb_data, status, error_message):
self.end_cnt += 1
self.end_error_message = error_message
return 0

def progress(self, user_cb_data, total_to_download, downloaded):
self.progress_cnt += 1
return 0

def fastest_mirror(self, user_cb_data, stage, ptr):
self.fastest_mirror_cnt += 1

Expand Down Expand Up @@ -77,13 +64,9 @@ def test_load_repo(self):

self.repo_sack.load_repos(libdnf5.repo.Repo.Type_AVAILABLE)

self.assertEqual(dl_cbs.start_cnt, 1)
self.assertEqual(dl_cbs.start_what, repoid)

self.assertEqual(dl_cbs.end_cnt, 1)
self.assertEqual(dl_cbs.end_error_message, None)

self.assertGreaterEqual(dl_cbs.progress_cnt, 1)
self.assertEqual(dl_cbs.fastest_mirror_cnt, 0)
self.assertEqual(dl_cbs.handle_mirror_failure_cnt, 0)
self.assertEqual(cbs.repokey_import_cnt, 0)
Expand All @@ -101,13 +84,9 @@ def test_load_repo_overload(self):

self.repo_sack.load_repos()

self.assertEqual(dl_cbs.start_cnt, 1)
self.assertEqual(dl_cbs.start_what, repoid)

self.assertEqual(dl_cbs.end_cnt, 1)
self.assertEqual(dl_cbs.end_error_message, None)

self.assertGreaterEqual(dl_cbs.progress_cnt, 1)
self.assertEqual(dl_cbs.fastest_mirror_cnt, 0)
self.assertEqual(dl_cbs.handle_mirror_failure_cnt, 0)
self.assertEqual(cbs.repokey_import_cnt, 0)
Loading

0 comments on commit dabead7

Please sign in to comment.