Skip to content

Commit

Permalink
Add libauracle unit tests
Browse files Browse the repository at this point in the history
Cover sort, format, and the PackageCache modules. Some of this overlaps
with our integration tests, but it's nice to have coverage at multiple
levels and the tests are fast enough.
  • Loading branch information
falconindy committed May 26, 2019
1 parent 5d4a162 commit 5e7bcad
Show file tree
Hide file tree
Showing 8 changed files with 460 additions and 45 deletions.
47 changes: 34 additions & 13 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ configure_file(
output : 'config.h',
configuration : conf)

add_project_arguments('-include', 'config.h', language : 'cpp')
add_project_arguments(
'-include', 'config.h',
language : 'cpp')

possible_cpp_flags = []
possible_link_flags = []
Expand Down Expand Up @@ -59,7 +61,6 @@ libaur = static_library(
src/aur/json_internal.hh
'''.split()),
include_directories : [
'src',
'third_party/nlohmann_json',
],
dependencies : [libcurl, libsystemd, stdcppfs])
Expand Down Expand Up @@ -133,19 +134,39 @@ if gtest.found() and gmock.found()
'src/test/gtest_main.cc')

foreach input : [
'src/aur/request_test.cc',
'src/aur/response_test.cc',
{
'prefix': 'libaur',
'link_with' : [libaur],
'tests' : [
'src/aur/request_test.cc',
'src/aur/response_test.cc',
],
},
{
'prefix': 'libauracle',
'link_with' : [libauracle],
'tests' : [
'src/auracle/package_cache_test.cc',
'src/auracle/format_test.cc',
'src/auracle/sort_test.cc',
],
},
]
basename = input.split('/')[-1].split('.')[0]

test(
basename,
executable(
basename,
input,
link_with : [libaur, gtest_main],
dependencies : [gtest, gmock]))
foreach source : input.get('tests')
basename = source.split('/')[-1].split('.')[0]
test(
'@0@_@1@'.format(input.get('prefix'), basename),
executable(
basename,
source,
include_directories : [
'src',
],
link_with : [gtest_main] + input.get('link_with'),
dependencies : [gtest, gmock]))
endforeach
endforeach
else
message('Skipping unit tests, gtest or gmock not found')
endif
Expand All @@ -169,7 +190,7 @@ if py3.found() and py3.language_version().version_compare(python_requirement)
basename = input.split('/')[-1].split('.')[0]

test(
'@0@_integration_test'.format(basename),
'auracle_@0@_integration_test'.format(basename),
py3,
args : [join_paths(meson.source_root(), input)],
env : ['PYTHONDONTWRITEBYTECODE=1'])
Expand Down
8 changes: 8 additions & 0 deletions src/aur/package.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,12 @@ void from_json(const nlohmann::json& j, Package& p) {
DeserializeJsonObject(j, callbacks, p);
}

Package::Package(const std::string& json_bytes) {
if (json_bytes.empty()) {
return;
}

*this = nlohmann::json::parse(json_bytes);
}

} // namespace aur
3 changes: 3 additions & 0 deletions src/aur/package.hh
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ struct Dependency {
};

struct Package {
Package() = default;
explicit Package(const std::string& json_bytes);

std::string name;
std::string description;
std::string maintainer;
Expand Down
72 changes: 40 additions & 32 deletions src/auracle/format.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <fmt/printf.h>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string_view>

Expand Down Expand Up @@ -140,7 +141,7 @@ struct formatter<Field<T>> {
namespace format {

void NameOnly(const aur::Package& package) {
fmt::print(terminal::Bold("{}\n"), package.name);
std::cout << fmt::format(terminal::Bold("{}\n"), package.name);
}

void Short(const aur::Package& package,
Expand All @@ -162,9 +163,10 @@ void Short(const aur::Package& package,
fmt::format("[installed: {}]", local_ver_color(l->pkgver));
}

fmt::print("{}{} {} ({}, {}) {}\n {}\n", t::BoldMagenta("aur/"),
t::Bold(p.name), ood_color(p.version), p.votes, p.popularity,
installed_package, p.description);
std::cout << fmt::format("{}{} {} ({}, {}) {}\n {}\n",
t::BoldMagenta("aur/"), t::Bold(p.name),
ood_color(p.version), p.votes, p.popularity,
installed_package, p.description);
}

void Long(const aur::Package& package,
Expand All @@ -187,48 +189,52 @@ void Long(const aur::Package& package,
fmt::format(" [installed: {}]", local_ver_color(l->pkgver));
}

fmt::print("{}", Field("Repository", t::BoldMagenta("aur")));
fmt::print("{}", Field("Name", p.name));
fmt::print("{}", Field("Version", ood_color(p.version) + installed_package));
std::cout << fmt::format("{}", Field("Repository", t::BoldMagenta("aur")));
std::cout << fmt::format("{}", Field("Name", p.name));
std::cout << fmt::format(
"{}", Field("Version", ood_color(p.version) + installed_package));

if (p.name != p.pkgbase) {
fmt::print("{}", Field("PackageBase", p.pkgbase));
std::cout << fmt::format("{}", Field("PackageBase", p.pkgbase));
}

fmt::print("{}", Field("URL", t::BoldCyan(p.upstream_url)));
fmt::print(
std::cout << fmt::format("{}", Field("URL", t::BoldCyan(p.upstream_url)));
std::cout << fmt::format(
"{}", Field("AUR Page",
t::BoldCyan("https://aur.archlinux.org/packages/" + p.name)));
fmt::print("{}", Field("Keywords", p.keywords));
fmt::print("{}", Field("Groups", p.groups));
fmt::print("{}", Field("Depends On", p.depends));
fmt::print("{}", Field("Makedepends", p.makedepends));
fmt::print("{}", Field("Checkdepends", p.checkdepends));
fmt::print("{}", Field("Provides", p.provides));
fmt::print("{}", Field("Conflicts With", p.conflicts));
fmt::print("{}", Field("Optional Deps", p.optdepends));
fmt::print("{}", Field("Replaces", p.replaces));
fmt::print("{}", Field("Licenses", p.licenses));
fmt::print("{}", Field("Votes", p.votes));
fmt::print("{}", Field("Popularity", p.popularity));
fmt::print("{}", Field("Maintainer",
p.maintainer.empty() ? "(orphan)" : p.maintainer));
fmt::print("{}", Field("Submitted", p.submitted_s));
fmt::print("{}", Field("Last Modified", p.modified_s));
std::cout << fmt::format("{}", Field("Keywords", p.keywords));
std::cout << fmt::format("{}", Field("Groups", p.groups));
std::cout << fmt::format("{}", Field("Depends On", p.depends));
std::cout << fmt::format("{}", Field("Makedepends", p.makedepends));
std::cout << fmt::format("{}", Field("Checkdepends", p.checkdepends));
std::cout << fmt::format("{}", Field("Provides", p.provides));
std::cout << fmt::format("{}", Field("Conflicts With", p.conflicts));
std::cout << fmt::format("{}", Field("Optional Deps", p.optdepends));
std::cout << fmt::format("{}", Field("Replaces", p.replaces));
std::cout << fmt::format("{}", Field("Licenses", p.licenses));
std::cout << fmt::format("{}", Field("Votes", p.votes));
std::cout << fmt::format("{}", Field("Popularity", p.popularity));
std::cout << fmt::format(
"{}",
Field("Maintainer", p.maintainer.empty() ? "(orphan)" : p.maintainer));
std::cout << fmt::format("{}", Field("Submitted", p.submitted_s));
std::cout << fmt::format("{}", Field("Last Modified", p.modified_s));
if (p.out_of_date != std::chrono::seconds::zero()) {
fmt::print("{}", Field("Out of Date", p.out_of_date));
std::cout << fmt::format("{}", Field("Out of Date", p.out_of_date));
}
fmt::print("{}", Field("Description", p.description));
fmt::print("\n");
std::cout << fmt::format("{}", Field("Description", p.description));
std::cout << fmt::format("\n");
}

void Update(const auracle::Pacman::Package& from, const aur::Package& to) {
namespace t = terminal;

fmt::print("{} {} -> {}\n", t::Bold(from.pkgname), t::BoldRed(from.pkgver),
t::BoldGreen(to.version));
std::cout << fmt::format("{} {} -> {}\n", t::Bold(from.pkgname),
t::BoldRed(from.pkgver), t::BoldGreen(to.version));
}

namespace {

void FormatCustomTo(std::string& out, const std::string& format,
const aur::Package& package) {
// clang-format off
Expand Down Expand Up @@ -262,12 +268,14 @@ void FormatCustomTo(std::string& out, const std::string& format,
// clang-format on
}

} // namespace

void Custom(const std::string& format, const aur::Package& package) {
std::string out;

FormatCustomTo(out, format, package);

fmt::print("{}\n", out);
std::cout << out << "\n";
}

bool FormatIsValid(const std::string& format, std::string* error) {
Expand Down
100 changes: 100 additions & 0 deletions src/auracle/format_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#include "format.hh"

#include <iostream>
#include <sstream>

#include "aur/package.hh"
#include "gtest/gtest.h"

class ScopedCapturer {
public:
ScopedCapturer(std::ostream& stream) : stream_(stream) {
stream_.rdbuf(buffer_.rdbuf());
}

~ScopedCapturer() { stream_.rdbuf(original_sbuf_); }

std::string GetCapturedOutput() {
auto str = buffer_.str();
buffer_.str(std::string());
return str;
}

private:
std::stringstream buffer_;
std::streambuf* original_sbuf_ = std::cout.rdbuf();
std::ostream& stream_;
};

aur::Package MakePackage() {
aur::Package p;

// string
p.name = "cower";
p.version = "1.2.3";

// floating point
p.popularity = 5.20238;

// datetime
p.submitted_s = std::chrono::seconds(1499013608);

// lists
p.conflicts = {
"auracle",
"cower",
"cower-git",
};

return p;
}

TEST(FormatTest, DetectsInvalidFormats) {
std::string err;
EXPECT_FALSE(format::FormatIsValid("{invalid}", &err));
EXPECT_FALSE(err.empty());
}

TEST(FormatTest, CustomStringFormat) {
ScopedCapturer capture(std::cout);

format::Custom("{name} -> {version}", MakePackage());

EXPECT_EQ(capture.GetCapturedOutput(), "cower -> 1.2.3\n");
}

TEST(FormatTest, CustomFloatFormat) {
ScopedCapturer capture(std::cout);

auto p = MakePackage();

format::Custom("{popularity}", p);
EXPECT_EQ(capture.GetCapturedOutput(), "5.20238\n");

format::Custom("{popularity:.2f}", p);
EXPECT_EQ(capture.GetCapturedOutput(), "5.20\n");
}

TEST(FormatTest, CustomDateTimeFormat) {
ScopedCapturer capture(std::cout);

auto p = MakePackage();

format::Custom("{submitted}", p);
EXPECT_EQ(capture.GetCapturedOutput(), "Sun Jul 2 16:40:08 2017\n");

format::Custom("{submitted:%s}", p);
EXPECT_EQ(capture.GetCapturedOutput(), "1499013608\n");
}

TEST(FormatTest, ListFormat) {
ScopedCapturer capture(std::cout);

auto p = MakePackage();

format::Custom("{conflicts}", p);
EXPECT_EQ(capture.GetCapturedOutput(), "auracle cower cower-git\n");

format::Custom("{conflicts::,,}", p);
EXPECT_EQ(capture.GetCapturedOutput(), "auracle:,,cower:,,cower-git\n");
}
Loading

1 comment on commit 5e7bcad

@stefanhusmann
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Build ends with "call of overloaded 'Package(const nlohmann::basic_json<>&)' is ambiguous"

buildlog.txt

Please sign in to comment.