Skip to content

Commit 9b118c6

Browse files
reddevillgComixHe
authored andcommitted
fix: fix logging and mergeOutput
- `fmt::println(stderr, message)` could crash if the message contained format specifiers like `{}`. - fix the `mergeOutput` logic and extract it from the `Builder` class into a free function within the `detail` namespace. This refactoring allows for easier unit testing. - Unit tests have been added for both `mergeOutput` function and the logging format fix.
1 parent 588fd5c commit 9b118c6

5 files changed

Lines changed: 108 additions & 38 deletions

File tree

libs/linglong/src/linglong/builder/linglong_builder.cpp

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,41 @@ utils::error::Result<void> pullDependency(const package::Reference &ref,
142142

143143
} // namespace
144144

145+
namespace detail {
146+
void mergeOutput(const std::vector<std::filesystem::path> &src,
147+
const std::filesystem::path &dest,
148+
const std::vector<std::string> &targets)
149+
{
150+
for (const auto &dir : src) {
151+
LogD("merge {} to {}", dir, dest);
152+
auto matcher = [&dir, &targets](const std::filesystem::path &path) {
153+
if (common::strings::starts_with(path.filename().string(), ".wh.")) {
154+
return false;
155+
}
156+
157+
struct stat st;
158+
if (-1 == lstat((dir / path).c_str(), &st)) {
159+
return false;
160+
}
161+
if (st.st_size == 0 && st.st_rdev == 0 && st.st_mode == S_IFCHR) {
162+
return false;
163+
}
164+
165+
for (const auto &target : targets) {
166+
if (common::strings::starts_with(path.string(), target)) {
167+
return true;
168+
}
169+
}
170+
171+
return false;
172+
};
173+
174+
utils::copyDirectory(dir, dest, matcher);
175+
}
176+
}
177+
178+
} // namespace detail
179+
145180
// install module files by rules
146181
// files will be moved from buildOutput to moduleOutput
147182
utils::error::Result<std::vector<std::filesystem::path>>
@@ -904,7 +939,7 @@ utils::error::Result<void> Builder::buildStagePreCommit() noexcept
904939
src.push_back(runtimeOverlay->upperDirPath());
905940
}
906941
}
907-
mergeOutput(src, buildOutput, { "bin/", "sbin/", "lib/" });
942+
detail::mergeOutput(src, buildOutput, { "bin/", "sbin/", "lib/" });
908943

909944
return LINGLONG_OK;
910945
}
@@ -2189,38 +2224,6 @@ void Builder::takeTerminalForeground()
21892224
}
21902225
}
21912226

2192-
void Builder::mergeOutput(const std::vector<std::filesystem::path> &src,
2193-
const std::filesystem::path &dest,
2194-
const std::vector<std::string> &targets)
2195-
{
2196-
2197-
for (const auto &dir : src) {
2198-
auto matcher = [&dir, &targets](const std::filesystem::path &path) {
2199-
if (path.filename().string().rfind(".wh.", 0) == 0) {
2200-
return false;
2201-
}
2202-
2203-
struct stat st;
2204-
if (-1 == lstat(path.c_str(), &st)) {
2205-
return false;
2206-
}
2207-
if (st.st_size == 0 && st.st_rdev == 0 && st.st_mode == S_IFCHR) {
2208-
return false;
2209-
}
2210-
2211-
for (const auto &target : targets) {
2212-
if (path.lexically_relative(dir).string().rfind(target, 0) == 0) {
2213-
return true;
2214-
}
2215-
}
2216-
2217-
return false;
2218-
};
2219-
2220-
utils::copyDirectory(dir, dest, matcher);
2221-
}
2222-
}
2223-
22242227
void Builder::printBasicInfo()
22252228
{
22262229
printMessage("[Builder info]");

libs/linglong/src/linglong/builder/linglong_builder.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ utils::error::Result<void> cmdRemoveApp(repo::OSTreeRepo &repo,
5353
std::vector<std::string> refs,
5454
bool prune);
5555

56+
namespace detail {
57+
void mergeOutput(const std::vector<std::filesystem::path> &src,
58+
const std::filesystem::path &dest,
59+
const std::vector<std::string> &targets);
60+
}
61+
5662
class Builder
5763
{
5864
public:
@@ -128,9 +134,6 @@ class Builder
128134
auto generateBuildDependsScript() noexcept -> utils::error::Result<bool>;
129135
auto generateDependsScript() noexcept -> utils::error::Result<bool>;
130136
void takeTerminalForeground();
131-
void mergeOutput(const std::vector<std::filesystem::path> &src,
132-
const std::filesystem::path &dest,
133-
const std::vector<std::string> &targets);
134137
void printBasicInfo();
135138
void printRepo();
136139
bool checkDeprecatedInstallFile();

libs/linglong/tests/ll-tests/src/linglong/builder/linglong_builder_test.cpp

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,53 @@ TEST(LinglongBuilder, installModule)
138138
EXPECT_EQ(installedFiles, expectedFiles);
139139
}
140140

141+
TEST(LinglongBuilder, mergeOutput)
142+
{
143+
TempDir srcDir1;
144+
ASSERT_TRUE(srcDir1.isValid());
145+
TempDir srcDir2;
146+
ASSERT_TRUE(srcDir2.isValid());
147+
TempDir destDir;
148+
ASSERT_TRUE(destDir.isValid());
149+
150+
// Create test files and directories
151+
const auto &srcPath1 = srcDir1.path();
152+
std::filesystem::create_directories(srcPath1 / "bin");
153+
std::filesystem::create_directories(srcPath1 / "lib");
154+
std::filesystem::create_directories(srcPath1 / "share");
155+
156+
std::ofstream(srcPath1 / "bin/tool1");
157+
std::ofstream(srcPath1 / "lib/libfoo.so");
158+
std::ofstream(srcPath1 / "share/data1");
159+
std::ofstream(srcPath1 / ".wh.somefile");
160+
161+
const auto &srcPath2 = srcDir2.path();
162+
std::filesystem::create_directories(srcPath2 / "bin");
163+
std::filesystem::create_directories(srcPath2 / "lib");
164+
std::filesystem::create_directories(srcPath2 / "share");
165+
166+
std::ofstream(srcPath2 / "bin/tool2");
167+
std::ofstream(srcPath2 / "lib/libbar.so");
168+
std::ofstream(srcPath2 / "share/data2");
169+
170+
// Define merge targets
171+
std::vector<std::string> targets = { "bin/", "share/data1" };
172+
173+
linglong::builder::detail::mergeOutput({ srcPath1, srcPath2 }, destDir.path(), targets);
174+
175+
const auto &destPath = destDir.path();
176+
// Check files are merged
177+
EXPECT_TRUE(std::filesystem::exists(destPath / "bin/tool1"));
178+
EXPECT_TRUE(std::filesystem::exists(destPath / "bin/tool2"));
179+
EXPECT_TRUE(std::filesystem::exists(destPath / "share/data1"));
180+
181+
// Check files are NOT merged
182+
EXPECT_FALSE(std::filesystem::exists(destPath / "lib/libfoo.so"));
183+
EXPECT_FALSE(std::filesystem::exists(destPath / "lib/libbar.so"));
184+
EXPECT_FALSE(std::filesystem::exists(destPath / "share/data2"));
185+
EXPECT_FALSE(std::filesystem::exists(destPath / ".wh.somefile"));
186+
}
187+
141188
TEST(LinglongBuilder, UabExportFilename)
142189
{
143190
linglong::builder::BuilderMock builder;
@@ -156,4 +203,4 @@ TEST(LinglongBuilder, LayerExportFilename)
156203
EXPECT_TRUE(ref.has_value()) << ref.error().message();
157204
auto filename = builder.layerExportFilename(*ref, "binary");
158205
EXPECT_EQ(filename, "org.deepin.demo_1.0.0.0_arm64_binary.layer");
159-
};
206+
};

libs/linglong/tests/ll-tests/src/linglong/utils/log.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,3 +224,20 @@ TEST_F(LoggerTest, MessageFormattingWorksCorrectly)
224224
ASSERT_TRUE(mock_journal_data.called);
225225
EXPECT_EQ(mock_journal_data.fields["MESSAGE"], "Hello, world! The number is 42.");
226226
}
227+
228+
TEST_F(LoggerTest, LogFormat)
229+
{
230+
logger_.setLogLevel(LogLevel::Debug);
231+
logger_.setLogBackend(LogBackend::Console);
232+
233+
std::string captured_output;
234+
{
235+
StderrRedirector redirector;
236+
EXPECT_TRUE(redirector.init());
237+
std::string message = "message is {}";
238+
logger_.log(context_, LogLevel::Debug, "Debug: {}", message);
239+
captured_output = redirector.getOutput();
240+
}
241+
242+
EXPECT_EQ("Debug: message is {}\n", captured_output);
243+
}

libs/utils/src/linglong/utils/log/log.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class Logger
9797
}
9898

9999
if ((logBackend & LogBackend::Console) != LogBackend::None) {
100-
fmt::println(stderr, message);
100+
fmt::println(stderr, "{}", message);
101101
}
102102

103103
if ((logBackend & LogBackend::Journal) != LogBackend::None) {

0 commit comments

Comments
 (0)