#include <apt-pkg/fileutl.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/aptconfiguration.h>
+#include <apt-pkg/configuration.h>
+#include <algorithm>
#include <string>
#include <vector>
#include <stdlib.h>
EXPECT_N_STR(expect, readback);
EXPECT_EQ(test.size(), f.Tell());
}
+ // Non-zero backwards seek
+ {
+ APT_INIT_READBACK
+ char const * const expect = "is";
+ EXPECT_EQ(test.size(), f.Tell());
+ EXPECT_TRUE(f.Seek(5));
+ EXPECT_TRUE(f.Read(readback, strlen(expect)));
+ EXPECT_FALSE(f.Failed());
+ EXPECT_FALSE(f.Eof());
+ EXPECT_N_STR(expect, readback);
+ EXPECT_EQ(7, f.Tell());
+ }
{
APT_INIT_READBACK
EXPECT_TRUE(f.Seek(0));
static void TestFileFd(unsigned int const filemode)
{
- std::vector<APT::Configuration::Compressor> compressors = APT::Configuration::getCompressors();
-
- // testing the (un)compress via pipe, as the 'real' compressors are usually built in via libraries
- compressors.push_back(APT::Configuration::Compressor("rev", ".reversed", "rev", NULL, NULL, 42));
- //compressors.push_back(APT::Configuration::Compressor("cat", ".ident", "cat", NULL, NULL, 42));
-
- for (std::vector<APT::Configuration::Compressor>::const_iterator c = compressors.begin(); c != compressors.end(); ++c)
+ auto const compressors = APT::Configuration::getCompressors();
+ EXPECT_EQ(7, compressors.size());
+ bool atLeastOneWasTested = false;
+ for (auto const &c: compressors)
{
if ((filemode & FileFd::ReadWrite) == FileFd::ReadWrite &&
- (c->Name.empty() != true && c->Binary.empty() != true))
+ (c.Name.empty() != true && c.Binary.empty() != true))
continue;
- TestFileFd(0002, 0664, filemode, *c);
- TestFileFd(0022, 0644, filemode, *c);
- TestFileFd(0077, 0600, filemode, *c);
- TestFileFd(0026, 0640, filemode, *c);
+ atLeastOneWasTested = true;
+ TestFileFd(0002, 0664, filemode, c);
+ TestFileFd(0022, 0644, filemode, c);
+ TestFileFd(0077, 0600, filemode, c);
+ TestFileFd(0026, 0640, filemode, c);
}
+ EXPECT_TRUE(atLeastOneWasTested);
}
TEST(FileUtlTest, FileFD)
{
+ // testing the (un)compress via pipe, as the 'real' compressors are usually built in via libraries
+ _config->Set("APT::Compressor::rev::Name", "rev");
+ _config->Set("APT::Compressor::rev::Extension", ".reversed");
+ _config->Set("APT::Compressor::rev::Binary", "rev");
+ _config->Set("APT::Compressor::rev::Cost", 10);
+ auto const compressors = APT::Configuration::getCompressors(false);
+ EXPECT_EQ(7, compressors.size());
+ EXPECT_TRUE(std::any_of(compressors.begin(), compressors.end(), [](APT::Configuration::Compressor const &c) { return c.Name == "rev"; }));
+
std::string const startdir = SafeGetCWD();
EXPECT_FALSE(startdir.empty());
std::string tempdir;
setenv("TMPDIR", "/not-there-no-really-not", 1);
EXPECT_EQ("/tmp", GetTempDir());
- // here but not accessible for non-roots
- setenv("TMPDIR", "/usr", 1);
- EXPECT_EQ("/tmp", GetTempDir());
+ // root can access everything, so /usr will be accepted
+ if (geteuid() != 0)
+ {
+ // here but not accessible for non-roots
+ setenv("TMPDIR", "/usr", 1);
+ EXPECT_EQ("/tmp", GetTempDir());
+ }
// files are no good for tmpdirs, too
setenv("TMPDIR", "/dev/null", 1);
TEST(FileUtlTest, flAbsPath)
{
std::string cwd = SafeGetCWD();
- int res = chdir("/bin/");
+ int res = chdir("/etc/");
EXPECT_EQ(res, 0);
- std::string p = flAbsPath("ls");
- EXPECT_EQ(p, "/bin/ls");
+ std::string p = flAbsPath("passwd");
+ EXPECT_EQ(p, "/etc/passwd");
res = chdir(cwd.c_str());
EXPECT_EQ(res, 0);
}
+
+static void TestDevNullFileFd(unsigned int const filemode)
+{
+ SCOPED_TRACE(filemode);
+ FileFd f("/dev/null", filemode);
+ EXPECT_FALSE(f.Failed());
+ EXPECT_TRUE(f.IsOpen());
+ EXPECT_TRUE(f.IsOpen());
+
+ std::string test = "This is a test!\n";
+ EXPECT_TRUE(f.Write(test.c_str(), test.size()));
+ EXPECT_TRUE(f.IsOpen());
+ EXPECT_FALSE(f.Failed());
+
+ f.Close();
+ EXPECT_FALSE(f.IsOpen());
+ EXPECT_FALSE(f.Failed());
+}
+TEST(FileUtlTest, WorkingWithDevNull)
+{
+ TestDevNullFileFd(FileFd::WriteOnly | FileFd::Create);
+ TestDevNullFileFd(FileFd::WriteOnly | FileFd::Create | FileFd::Empty);
+ TestDevNullFileFd(FileFd::WriteOnly | FileFd::Create | FileFd::Exclusive);
+ TestDevNullFileFd(FileFd::WriteOnly | FileFd::Atomic);
+ TestDevNullFileFd(FileFd::WriteOnly | FileFd::Create | FileFd::Atomic);
+ // short-hands for ReadWrite with these modes
+ TestDevNullFileFd(FileFd::WriteEmpty);
+ TestDevNullFileFd(FileFd::WriteAny);
+ TestDevNullFileFd(FileFd::WriteTemp);
+ TestDevNullFileFd(FileFd::WriteAtomic);
+}
+constexpr char const * const TESTSTRING = "This is a test";
+static void TestFailingAtomicKeepsFile(char const * const label, std::string const &filename)
+{
+ SCOPED_TRACE(label);
+ EXPECT_TRUE(FileExists(filename));
+ FileFd fd;
+ EXPECT_TRUE(fd.Open(filename, FileFd::ReadOnly));
+ char buffer[50];
+ EXPECT_NE(nullptr, fd.ReadLine(buffer, sizeof(buffer)));
+ EXPECT_STREQ(TESTSTRING, buffer);
+}
+TEST(FileUtlTest, FailingAtomic)
+{
+ FileFd fd;
+ std::string filename;
+ createTemporaryFile("failingatomic", fd, &filename, TESTSTRING);
+ TestFailingAtomicKeepsFile("init", filename);
+
+ FileFd f;
+ EXPECT_TRUE(f.Open(filename, FileFd::ReadWrite | FileFd::Atomic));
+ f.EraseOnFailure();
+ EXPECT_FALSE(f.Failed());
+ EXPECT_TRUE(f.IsOpen());
+ TestFailingAtomicKeepsFile("before-fail", filename);
+ EXPECT_TRUE(f.Write("Bad file write", 10));
+ f.OpFail();
+ EXPECT_TRUE(f.Failed());
+ TestFailingAtomicKeepsFile("after-fail", filename);
+ EXPECT_TRUE(f.Close());
+ TestFailingAtomicKeepsFile("closed", filename);
+
+ if (filename.empty() == false)
+ unlink(filename.c_str());
+}