]> git.saurik.com Git - apt.git/commitdiff
reimplement the last uses of sprintf
authorDavid Kalnischkies <david@kalnischkies.de>
Tue, 10 Mar 2015 13:11:54 +0000 (14:11 +0100)
committerDavid Kalnischkies <david@kalnischkies.de>
Fri, 10 Apr 2015 18:18:17 +0000 (20:18 +0200)
Working with strings c-style is complicated and error-prune,
so by converting to c++ style we gain some simplicity and
avoid buffer overflows by later extensions.

Git-Dch: Ignore

apt-pkg/contrib/cdromutl.cc
apt-pkg/contrib/strutl.cc
apt-private/acqprogress.cc
apt-private/acqprogress.h
ftparchive/writer.cc
methods/ftp.cc
test/libapt/strutil_test.cc
test/libapt/uri_test.cc

index 936e377fbfe6af2777bc2c6133e4eb945a6d552a..6eb917457c62c9c45d5dafee59955385ae3113c5 100644 (file)
@@ -207,7 +207,6 @@ bool IdentCdrom(string CD,string &Res,unsigned int Version)
    /* Run over the directory, we assume that the reader order will never
       change as the media is read-only. In theory if the kernel did
       some sort of wacked caching this might not be true.. */
-   char S[300];
    for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
    {
       // Skip some files..
@@ -215,30 +214,32 @@ bool IdentCdrom(string CD,string &Res,unsigned int Version)
          strcmp(Dir->d_name,"..") == 0)
         continue;
 
+      std::string S;
       if (Version <= 1)
       {
-        sprintf(S,"%lu",(unsigned long)Dir->d_ino);
+        strprintf(S, "%lu", (unsigned long)Dir->d_ino);
       }
       else
       {
         struct stat Buf;
         if (stat(Dir->d_name,&Buf) != 0)
            continue;
-        sprintf(S,"%lu",(unsigned long)Buf.st_mtime);
+        strprintf(S, "%lu", (unsigned long)Buf.st_mtime);
       }
-      
-      Hash.Add(S);
+
+      Hash.Add(S.c_str());
       Hash.Add(Dir->d_name);
    };
-   
+
    if (chdir(StartDir.c_str()) != 0) {
       _error->Errno("chdir",_("Unable to change to %s"),StartDir.c_str());
       closedir(D);
       return false;
    }
    closedir(D);
-   
+
    // Some stats from the fsys
+   std::string S;
    if (_config->FindB("Debug::identcdrom",false) == false)
    {
       struct statvfs Buf;
@@ -248,19 +249,19 @@ bool IdentCdrom(string CD,string &Res,unsigned int Version)
       // We use a kilobyte block size to advoid overflow
       if (writable_media)
       {
-         sprintf(S,"%lu",(long)(Buf.f_blocks*(Buf.f_bsize/1024)));
+         strprintf(S, "%lu", (unsigned long)(Buf.f_blocks*(Buf.f_bsize/1024)));
       } else {
-         sprintf(S,"%lu %lu",(long)(Buf.f_blocks*(Buf.f_bsize/1024)),
-                 (long)(Buf.f_bfree*(Buf.f_bsize/1024)));
+         strprintf(S, "%lu %lu", (unsigned long)(Buf.f_blocks*(Buf.f_bsize/1024)),
+                 (unsigned long)(Buf.f_bfree*(Buf.f_bsize/1024)));
       }
-      Hash.Add(S);
-      sprintf(S,"-%u",Version);
+      Hash.Add(S.c_str());
+      strprintf(S, "-%u", Version);
    }
    else
-      sprintf(S,"-%u.debug",Version);
-   
+      strprintf(S, "-%u.debug", Version);
+
    Res = Hash.Result().Value() + S;
-   return true;   
+   return true;
 }
                                                                        /*}}}*/
 // FindMountPointForDevice - Find mountpoint for the given device      /*{{{*/
index 0ac587a9e22b111e796aff07791a8209a4a82d30..0db4c57b249f9e20fea0d0f3a7b40b4d811736f8 100644 (file)
@@ -324,21 +324,19 @@ bool ParseCWord(const char *&String,string &Res)
 /* */
 string QuoteString(const string &Str, const char *Bad)
 {
-   string Res;
+   std::stringstream Res;
    for (string::const_iterator I = Str.begin(); I != Str.end(); ++I)
    {
-      if (strchr(Bad,*I) != 0 || isprint(*I) == 0 || 
+      if (strchr(Bad,*I) != 0 || isprint(*I) == 0 ||
          *I == 0x25 || // percent '%' char
          *I <= 0x20 || *I >= 0x7F) // control chars
       {
-        char Buf[10];
-        sprintf(Buf,"%%%02x",(int)*I);
-        Res += Buf;
+        ioprintf(Res,"%%%02x",(int)*I);
       }
       else
-        Res += *I;
+        Res << *I;
    }
-   return Res;
+   return Res.str();
 }
                                                                        /*}}}*/
 // DeQuoteString - Convert a string from quoted from                    /*{{{*/
@@ -379,13 +377,12 @@ string DeQuoteString(string::const_iterator const &begin,
    YottaBytes (E24) */
 string SizeToStr(double Size)
 {
-   char S[300];
    double ASize;
    if (Size >= 0)
       ASize = Size;
    else
       ASize = -1*Size;
-   
+
    /* bytes, KiloBytes, MegaBytes, GigaBytes, TeraBytes, PetaBytes, 
       ExaBytes, ZettaBytes, YottaBytes */
    char Ext[] = {'\0','k','M','G','T','P','E','Z','Y'};
@@ -394,20 +391,21 @@ string SizeToStr(double Size)
    {
       if (ASize < 100 && I != 0)
       {
-         sprintf(S,"%'.1f %c",ASize,Ext[I]);
-        break;
+        std::string S;
+        strprintf(S, "%'.1f %c", ASize, Ext[I]);
+        return S;
       }
-      
+
       if (ASize < 10000)
       {
-         sprintf(S,"%'.0f %c",ASize,Ext[I]);
-        break;
+        std::string S;
+        strprintf(S, "%'.0f %c", ASize, Ext[I]);
+        return S;
       }
       ASize /= 1000.0;
       I++;
    }
-   
-   return S;
+   return "";
 }
                                                                        /*}}}*/
 // TimeToStr - Convert the time into a string                          /*{{{*/
@@ -415,36 +413,27 @@ string SizeToStr(double Size)
 /* Converts a number of seconds to a hms format */
 string TimeToStr(unsigned long Sec)
 {
-   char S[300];
-   
-   while (1)
+   std::string S;
+   if (Sec > 60*60*24)
    {
-      if (Sec > 60*60*24)
-      {
-        //d means days, h means hours, min means minutes, s means seconds
-        sprintf(S,_("%lid %lih %limin %lis"),Sec/60/60/24,(Sec/60/60) % 24,(Sec/60) % 60,Sec % 60);
-        break;
-      }
-      
-      if (Sec > 60*60)
-      {
-        //h means hours, min means minutes, s means seconds
-        sprintf(S,_("%lih %limin %lis"),Sec/60/60,(Sec/60) % 60,Sec % 60);
-        break;
-      }
-      
-      if (Sec > 60)
-      {
-        //min means minutes, s means seconds
-        sprintf(S,_("%limin %lis"),Sec/60,Sec % 60);
-        break;
-      }
-
-      //s means seconds
-      sprintf(S,_("%lis"),Sec);
-      break;
+      //TRANSLATOR: d means days, h means hours, min means minutes, s means seconds
+      strprintf(S,_("%lid %lih %limin %lis"),Sec/60/60/24,(Sec/60/60) % 24,(Sec/60) % 60,Sec % 60);
+   }
+   else if (Sec > 60*60)
+   {
+      //TRANSLATOR: h means hours, min means minutes, s means seconds
+      strprintf(S,_("%lih %limin %lis"),Sec/60/60,(Sec/60) % 60,Sec % 60);
+   }
+   else if (Sec > 60)
+   {
+      //TRANSLATOR: min means minutes, s means seconds
+      strprintf(S,_("%limin %lis"),Sec/60,Sec % 60);
+   }
+   else
+   {
+      //TRANSLATOR: s means seconds
+      strprintf(S,_("%lis"),Sec);
    }
-   
    return S;
 }
                                                                        /*}}}*/
@@ -1423,7 +1412,7 @@ size_t strv_length(const char **str_array)
       ;
    return i;
 }
-
+                                                                       /*}}}*/
 // DeEscapeString - unescape (\0XX and \xXX) from a string             /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -1605,51 +1594,46 @@ void URI::CopyFrom(const string &U)
 /* */
 URI::operator string()
 {
-   string Res;
-   
+   std::stringstream Res;
+
    if (Access.empty() == false)
-      Res = Access + ':';
-   
+      Res << Access << ':';
+
    if (Host.empty() == false)
-   {    
+   {
       if (Access.empty() == false)
-        Res += "//";
-          
+        Res << "//";
+
       if (User.empty() == false)
       {
         // FIXME: Technically userinfo is permitted even less
         // characters than these, but this is not conveniently
         // expressed with a blacklist.
-        Res += QuoteString(User, ":/?#[]@");
+        Res << QuoteString(User, ":/?#[]@");
         if (Password.empty() == false)
-           Res += ":" + QuoteString(Password, ":/?#[]@");
-        Res += "@";
+           Res << ":" << QuoteString(Password, ":/?#[]@");
+        Res << "@";
       }
-      
+
       // Add RFC 2732 escaping characters
-      if (Access.empty() == false &&
-         (Host.find('/') != string::npos || Host.find(':') != string::npos))
-        Res += '[' + Host + ']';
+      if (Access.empty() == false && Host.find_first_of("/:") != string::npos)
+        Res << '[' << Host << ']';
       else
-        Res += Host;
-      
+        Res << Host;
+
       if (Port != 0)
-      {
-        char S[30];
-        sprintf(S,":%u",Port);
-        Res += S;
-      }         
+        Res << ':' << Port;
    }
-   
+
    if (Path.empty() == false)
    {
       if (Path[0] != '/')
-        Res += "/" + Path;
+        Res << "/" << Path;
       else
-        Res += Path;
+        Res << Path;
    }
-   
-   return Res;
+
+   return Res.str();
 }
                                                                        /*}}}*/
 // URI::SiteOnly - Return the schema and site for the URI              /*{{{*/
index 14a53eacb495e61078baf2d36a542e4bbb0184a2..e834d7d6ac8e9bcb411565b8154f8d032a5217bf 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdio.h>
 #include <signal.h>
 #include <iostream>
+#include <sstream>
 #include <unistd.h>
 
 #include <apti18n.h>
@@ -34,9 +35,8 @@ using namespace std;
 // ---------------------------------------------------------------------
 /* */
 AcqTextStatus::AcqTextStatus(unsigned int &ScreenWidth,unsigned int const Quiet) :
-    pkgAcquireStatus(), ScreenWidth(ScreenWidth), ID(0), Quiet(Quiet)
+    pkgAcquireStatus(), ScreenWidth(ScreenWidth), LastLineLength(0), ID(0), Quiet(Quiet)
 {
-   BlankLine[0] = 0;
    // testcases use it to disable pulses without disabling other user messages
    if (Quiet == 0 && _config->FindB("quiet::NoUpdate", false) == true)
       this->Quiet = 1;
@@ -48,7 +48,7 @@ AcqTextStatus::AcqTextStatus(unsigned int &ScreenWidth,unsigned int const Quiet)
 void AcqTextStatus::Start()
 {
    pkgAcquireStatus::Start();
-   BlankLine[0] = 0;
+   LastLineLength = 0;
    ID = 1;
 }
                                                                        /*}}}*/
@@ -60,8 +60,7 @@ void AcqTextStatus::IMSHit(pkgAcquire::ItemDesc &Itm)
    if (Quiet > 1)
       return;
 
-   if (Quiet <= 0)
-      cout << '\r' << BlankLine << '\r';
+   clearLastLine();
 
    cout << _("Hit ") << Itm.Description;
    cout << endl;
@@ -82,8 +81,7 @@ void AcqTextStatus::Fetch(pkgAcquire::ItemDesc &Itm)
    if (Quiet > 1)
       return;
 
-   if (Quiet <= 0)
-      cout << '\r' << BlankLine << '\r';
+   clearLastLine();
 
    cout << _("Get:") << Itm.Owner->ID << ' ' << Itm.Description;
    if (Itm.Owner->FileSize != 0)
@@ -111,8 +109,7 @@ void AcqTextStatus::Fail(pkgAcquire::ItemDesc &Itm)
    if (Itm.Owner->Status == pkgAcquire::Item::StatIdle)
       return;
 
-   if (Quiet <= 0)
-      cout << '\r' << BlankLine << '\r';
+   clearLastLine();
 
    if (Itm.Owner->Status == pkgAcquire::Item::StatDone)
    {
@@ -140,8 +137,7 @@ void AcqTextStatus::Stop()
    if (Quiet > 1)
       return;
 
-   if (Quiet <= 0)
-      cout << '\r' << BlankLine << '\r' << flush;
+   clearLastLine();
 
    if (_config->FindB("quiet::NoStatistic", false) == true)
       return;
@@ -167,77 +163,66 @@ bool AcqTextStatus::Pulse(pkgAcquire *Owner)
 
    enum {Long = 0,Medium,Short} Mode = Medium;
 
-   char Buffer[sizeof(BlankLine)];
-   char *End = Buffer + sizeof(Buffer);
-   char *S = Buffer;
-   if (ScreenWidth >= sizeof(Buffer))
-      ScreenWidth = sizeof(Buffer)-1;
-
-   // Put in the percent done
-   sprintf(S,"%.0f%%", Percent);
-
-   bool Shown = false;
-   for (pkgAcquire::Worker *I = Owner->WorkersBegin(); I != 0;
-       I = Owner->WorkerStep(I))
+   std::string Line;
    {
-      S += strlen(S);
-
-      // There is no item running
-      if (I->CurrentItem == 0)
+      std::stringstream S;
+      for (pkgAcquire::Worker *I = Owner->WorkersBegin(); I != 0;
+           I = Owner->WorkerStep(I))
       {
-        if (I->Status.empty() == false)
+        // There is no item running
+        if (I->CurrentItem == 0)
         {
-           snprintf(S,End-S," [%s]",I->Status.c_str());
-           Shown = true;
-        }
-
-        continue;
-      }
-
-      Shown = true;
+           if (I->Status.empty() == false)
+              S << " [" << I->Status << "]";
 
-      // Add in the short description
-      if (I->CurrentItem->Owner->ID != 0)
-        snprintf(S,End-S," [%lu %s",I->CurrentItem->Owner->ID,
-                 I->CurrentItem->ShortDesc.c_str());
-      else
-        snprintf(S,End-S," [%s",I->CurrentItem->ShortDesc.c_str());
-      S += strlen(S);
+           continue;
+        }
 
-      // Show the short mode string
-      if (I->CurrentItem->Owner->ActiveSubprocess.empty() == false)
-      {
-        snprintf(S,End-S, " %s", I->CurrentItem->Owner->ActiveSubprocess.c_str());
-        S += strlen(S);
-      }
+        // Add in the short description
+        S << " [";
+        if (I->CurrentItem->Owner->ID != 0)
+           S << I->CurrentItem->Owner->ID << " ";
+        S << I->CurrentItem->ShortDesc;
 
-      // Add the current progress
-      if (Mode == Long)
-        snprintf(S,End-S," %llu",I->CurrentSize);
-      else
-      {
-        if (Mode == Medium || I->TotalSize == 0)
-           snprintf(S,End-S," %sB",SizeToStr(I->CurrentSize).c_str());
-      }
-      S += strlen(S);
+        // Show the short mode string
+        if (I->CurrentItem->Owner->ActiveSubprocess.empty() == false)
+           S << " " << I->CurrentItem->Owner->ActiveSubprocess;
 
-      // Add the total size and percent
-      if (I->TotalSize > 0 && I->CurrentItem->Owner->Complete == false)
-      {
-        if (Mode == Short)
-           snprintf(S,End-S," %.0f%%",
-                    (I->CurrentSize*100.0)/I->TotalSize);
+        // Add the current progress
+        if (Mode == Long)
+           S << " " << I->CurrentSize;
         else
-           snprintf(S,End-S,"/%sB %.0f%%",SizeToStr(I->TotalSize).c_str(),
+        {
+           if (Mode == Medium || I->TotalSize == 0)
+              S << " " << SizeToStr(I->CurrentSize) << "B";
+        }
+
+        // Add the total size and percent
+        if (I->TotalSize > 0 && I->CurrentItem->Owner->Complete == false)
+        {
+           if (Mode == Short)
+              ioprintf(S, " %.0f%%", (I->CurrentSize*100.0)/I->TotalSize);
+           else
+              ioprintf(S, "/%sB %.0f%%", SizeToStr(I->TotalSize).c_str(),
                     (I->CurrentSize*100.0)/I->TotalSize);
+        }
+        S << "]";
       }
-      S += strlen(S);
-      snprintf(S,End-S,"]");
-   }
 
-   // Show something..
-   if (Shown == false)
-      snprintf(S,End-S,_(" [Working]"));
+      // Show at least something
+      Line = S.str();
+      S.clear();
+      if (Line.empty() == true)
+        Line = _(" [Working]");
+   }
+   // Put in the percent done
+   {
+      std::stringstream S;
+      ioprintf(S, "%.0f%%", Percent);
+      S << Line;
+      Line = S.str();
+      S.clear();
+   }
 
    /* Put in the ETA and cps meter, block off signals to prevent strangeness
       during resizing */
@@ -248,34 +233,33 @@ bool AcqTextStatus::Pulse(pkgAcquire *Owner)
 
    if (CurrentCPS != 0)
    {
-      char Tmp[300];
       unsigned long long ETA = (TotalBytes - CurrentBytes)/CurrentCPS;
-      sprintf(Tmp," %sB/s %s",SizeToStr(CurrentCPS).c_str(),TimeToStr(ETA).c_str());
-      unsigned int Len = strlen(Buffer);
-      unsigned int LenT = strlen(Tmp);
-      if (Len + LenT < ScreenWidth)
+      std::string Tmp = " " + SizeToStr(CurrentCPS) + "B/s " + TimeToStr(ETA);
+      size_t alignment = Line.length() + Tmp.length();
+      if (alignment < ScreenWidth)
       {
-        memset(Buffer + Len,' ',ScreenWidth - Len);
-        strcpy(Buffer + ScreenWidth - LenT,Tmp);
+        alignment = ScreenWidth - alignment;
+        for (size_t i = 0; i < alignment; ++i)
+           Line.append(" ");
+        Line.append(Tmp);
       }
    }
-   Buffer[ScreenWidth] = 0;
-   BlankLine[ScreenWidth] = 0;
+   if (Line.length() > ScreenWidth)
+      Line.erase(ScreenWidth);
    sigprocmask(SIG_SETMASK,&OldSigs,0);
 
    // Draw the current status
    if (_config->FindB("Apt::Color", false) == true)
       cout << _config->Find("APT::Color::Yellow");
-   if (strlen(Buffer) == strlen(BlankLine))
-      cout << '\r' << Buffer << flush;
+   if (LastLineLength > Line.length())
+      clearLastLine();
    else
-      cout << '\r' << BlankLine << '\r' << Buffer << flush;
+      cout << '\r';
+   cout << Line << flush;
    if (_config->FindB("Apt::Color", false) == true)
       cout << _config->Find("APT::Color::Neutral") << flush;
 
-   memset(BlankLine,' ',strlen(Buffer));
-   BlankLine[strlen(Buffer)] = 0;
-
+   LastLineLength = Line.length();
    Update = false;
 
    return true;
@@ -296,8 +280,7 @@ bool AcqTextStatus::MediaChange(string Media,string Drive)
 
       return false;
 
-   if (Quiet <= 0)
-      cout << '\r' << BlankLine << '\r';
+   clearLastLine();
    ioprintf(cout,_("Media change: please insert the disc labeled\n"
                   " '%s'\n"
                   "in the drive '%s' and press enter\n"),
@@ -317,3 +300,17 @@ bool AcqTextStatus::MediaChange(string Media,string Drive)
    return bStatus;
 }
                                                                        /*}}}*/
+void AcqTextStatus::clearLastLine() {                                  /*{{{*/
+   if (Quiet > 0)
+      return;
+
+   // do not try to clear more than the (now smaller) screen
+   if (LastLineLength > ScreenWidth)
+      LastLineLength = ScreenWidth;
+
+   std::cout << '\r';
+   for (size_t i = 0; i < LastLineLength; ++i)
+      std::cout << ' ';
+   std::cout << '\r' << std::flush;
+}
+                                                                       /*}}}*/
index 71a10d78afc6430a6103fa29289b1326857c1873..ab8170126c02b5a44286b79ae8f0319e93f1a4dc 100644 (file)
 class APT_PUBLIC AcqTextStatus : public pkgAcquireStatus
 {
    unsigned int &ScreenWidth;
-   char BlankLine[1024];
+   size_t LastLineLength;
    unsigned long ID;
    unsigned long Quiet;
 
+   void clearLastLine();
+
    public:
 
    virtual bool MediaChange(std::string Media,std::string Drive);
index a63d8846b155a92aee3622612218e4cdc9954ca3..db68c21f05f97f8e6204856e3d98564254c90666 100644 (file)
@@ -440,9 +440,6 @@ bool PackagesWriter::DoPackage(string FileName)
       OverItem->Priority = Tags.FindS("Priority");
    }
 
-   char Size[40];
-   sprintf(Size,"%llu", (unsigned long long) FileSize);
-   
    // Strip the DirStrip prefix from the FileName and add the PathPrefix
    string NewFileName;
    if (DirStrip.empty() == false &&
@@ -466,7 +463,10 @@ bool PackagesWriter::DoPackage(string FileName)
    // This lists all the changes to the fields we are going to make.
    std::vector<TFRewriteData> Changes;
 
-   Changes.push_back(SetTFRewriteData("Size", Size));
+   std::string Size;
+   strprintf(Size, "%llu", (unsigned long long) FileSize);
+   Changes.push_back(SetTFRewriteData("Size", Size.c_str()));
+
    for (HashStringList::const_iterator hs = Db.HashesList.begin(); hs != Db.HashesList.end(); ++hs)
    {
       if (hs->HashType() == "MD5Sum")
index 0504e58724f253025f1191282d2e0803af59b1f9..7764acf6a220f705b20257efcbb31c3279b30f08 100644 (file)
@@ -259,19 +259,21 @@ bool FTPConn::Login()
       {
         if (Opts->Value.empty() == true)
            continue;
-        
+
         // Substitute the variables into the command
-        char SitePort[20];
-        if (ServerName.Port != 0)
-           sprintf(SitePort,"%u",ServerName.Port);
-        else
-           strcpy(SitePort,"21");
         string Tmp = Opts->Value;
         Tmp = SubstVar(Tmp,"$(PROXY_USER)",Proxy.User);
         Tmp = SubstVar(Tmp,"$(PROXY_PASS)",Proxy.Password);
         Tmp = SubstVar(Tmp,"$(SITE_USER)",User);
         Tmp = SubstVar(Tmp,"$(SITE_PASS)",Pass);
-        Tmp = SubstVar(Tmp,"$(SITE_PORT)",SitePort);
+        if (ServerName.Port != 0)
+        {
+           std::string SitePort;
+           strprintf(SitePort, "%u", ServerName.Port);
+           Tmp = SubstVar(Tmp,"$(SITE_PORT)", SitePort);
+        }
+        else
+           Tmp = SubstVar(Tmp,"$(SITE_PORT)", "21");
         Tmp = SubstVar(Tmp,"$(SITE)",ServerName.Host);
 
         // Send the command
index 9bc3c76fdd12d86b1279b358762ed1081a968bc3..23dc08727a3edaa1d991e50593df9aa2bc4bca4d 100644 (file)
@@ -97,6 +97,28 @@ TEST(StrUtilTest,StartsWith)
    EXPECT_FALSE(Startswith("abcd", "x"));
    EXPECT_FALSE(Startswith("abcd", "abcndefg"));
 }
+TEST(StrUtilTest,TimeToStr)
+{
+   EXPECT_EQ("0s", TimeToStr(0));
+   EXPECT_EQ("42s", TimeToStr(42));
+   EXPECT_EQ("9min 21s", TimeToStr((9*60) + 21));
+   EXPECT_EQ("20min 42s", TimeToStr((20*60) + 42));
+   EXPECT_EQ("10h 42min 21s", TimeToStr((10*3600) + (42*60) + 21));
+   EXPECT_EQ("10h 42min 21s", TimeToStr((10*3600) + (42*60) + 21));
+   EXPECT_EQ("1988d 3h 29min 7s", TimeToStr((1988*86400) + (3*3600) + (29*60) + 7));
+
+   EXPECT_EQ("59s", TimeToStr(59));
+   EXPECT_EQ("60s", TimeToStr(60));
+   EXPECT_EQ("1min 1s", TimeToStr(61));
+   EXPECT_EQ("59min 59s", TimeToStr(3599));
+   EXPECT_EQ("60min 0s", TimeToStr(3600));
+   EXPECT_EQ("1h 0min 1s", TimeToStr(3601));
+   EXPECT_EQ("1h 1min 0s", TimeToStr(3660));
+   EXPECT_EQ("23h 59min 59s", TimeToStr(86399));
+   EXPECT_EQ("24h 0min 0s", TimeToStr(86400));
+   EXPECT_EQ("1d 0h 0min 1s", TimeToStr(86401));
+   EXPECT_EQ("1d 0h 1min 0s", TimeToStr(86460));
+}
 TEST(StrUtilTest,SubstVar)
 {
    EXPECT_EQ("", SubstVar("", "fails", "passes"));
index 1662f51f0e3ba3a24b6e93ba95fb79fa167c64a9..5d5ae9679da9d04ace35312355255abebaab1be5 100644 (file)
@@ -12,6 +12,7 @@ TEST(URITest, BasicHTTP)
    EXPECT_EQ(90, U.Port);
    EXPECT_EQ("www.debian.org", U.Host);
    EXPECT_EQ("/temp/test", U.Path);
+   EXPECT_EQ("http://www.debian.org:90/temp/test", (std::string)U);
    // Login data
    U = URI("http://jgg:foo@ualberta.ca/blah");
    EXPECT_EQ("http", U.Access);
@@ -20,6 +21,7 @@ TEST(URITest, BasicHTTP)
    EXPECT_EQ(0, U.Port);
    EXPECT_EQ("ualberta.ca", U.Host);
    EXPECT_EQ("/blah", U.Path);
+   EXPECT_EQ("http://jgg:foo@ualberta.ca/blah", (std::string)U);
 }
 TEST(URITest, SingeSlashFile)
 {
@@ -30,6 +32,7 @@ TEST(URITest, SingeSlashFile)
    EXPECT_EQ(0, U.Port);
    EXPECT_EQ("", U.Host);
    EXPECT_EQ("/usr/bin/foo", U.Path);
+   EXPECT_EQ("file:/usr/bin/foo", (std::string)U);
 }
 TEST(URITest, BasicCDROM)
 {
@@ -40,6 +43,7 @@ TEST(URITest, BasicCDROM)
    EXPECT_EQ(0, U.Port);
    EXPECT_EQ("Moo Cow Rom", U.Host);
    EXPECT_EQ("/debian", U.Path);
+   EXPECT_EQ("cdrom://Moo Cow Rom/debian", (std::string)U);
 }
 TEST(URITest, RelativeGzip)
 {
@@ -50,6 +54,7 @@ TEST(URITest, RelativeGzip)
    EXPECT_EQ(0, U.Port);
    EXPECT_EQ(".", U.Host);
    EXPECT_EQ("/bar/cow", U.Path);
+   EXPECT_EQ("gzip://./bar/cow", (std::string)U);
 }
 TEST(URITest, NoSlashFTP)
 {
@@ -60,6 +65,7 @@ TEST(URITest, NoSlashFTP)
    EXPECT_EQ(0, U.Port);
    EXPECT_EQ("ftp.fr.debian.org", U.Host);
    EXPECT_EQ("/debian/pool/main/x/xtel/xtel_3.2.1-15_i386.deb", U.Path);
+   EXPECT_EQ("ftp://ftp.fr.debian.org/debian/pool/main/x/xtel/xtel_3.2.1-15_i386.deb", (std::string)U);
 }
 TEST(URITest, RFC2732)
 {
@@ -70,6 +76,7 @@ TEST(URITest, RFC2732)
    EXPECT_EQ(0, U.Port);
    EXPECT_EQ("1080::8:800:200C:417A", U.Host);
    EXPECT_EQ("/foo", U.Path);
+   EXPECT_EQ("http://[1080::8:800:200C:417A]/foo", (std::string)U);
    // with port
    U = URI("http://[::FFFF:129.144.52.38]:80/index.html");
    EXPECT_EQ("http", U.Access);
@@ -78,6 +85,7 @@ TEST(URITest, RFC2732)
    EXPECT_EQ(80, U.Port);
    EXPECT_EQ("::FFFF:129.144.52.38", U.Host);
    EXPECT_EQ("/index.html", U.Path);
+   EXPECT_EQ("http://[::FFFF:129.144.52.38]:80/index.html", (std::string)U);
    // extra colon
    U = URI("http://[::FFFF:129.144.52.38:]:80/index.html");
    EXPECT_EQ("http", U.Access);
@@ -86,6 +94,7 @@ TEST(URITest, RFC2732)
    EXPECT_EQ(80, U.Port);
    EXPECT_EQ("::FFFF:129.144.52.38:", U.Host);
    EXPECT_EQ("/index.html", U.Path);
+   EXPECT_EQ("http://[::FFFF:129.144.52.38:]:80/index.html", (std::string)U);
    // extra colon port
    U = URI("http://[::FFFF:129.144.52.38:]/index.html");
    EXPECT_EQ("http", U.Access);
@@ -94,6 +103,7 @@ TEST(URITest, RFC2732)
    EXPECT_EQ(0, U.Port);
    EXPECT_EQ("::FFFF:129.144.52.38:", U.Host);
    EXPECT_EQ("/index.html", U.Path);
+   EXPECT_EQ("http://[::FFFF:129.144.52.38:]/index.html", (std::string)U);
    // My Evil Corruption of RFC 2732 to handle CDROM names!
    // Fun for the whole family! */
    U = URI("cdrom:[The Debian 1.2 disk, 1/2 R1:6]/debian/");
@@ -103,6 +113,7 @@ TEST(URITest, RFC2732)
    EXPECT_EQ(0, U.Port);
    EXPECT_EQ("The Debian 1.2 disk, 1/2 R1:6", U.Host);
    EXPECT_EQ("/debian/", U.Path);
+   EXPECT_EQ("cdrom://[The Debian 1.2 disk, 1/2 R1:6]/debian/", (std::string)U);
    // no brackets
    U = URI("cdrom:Foo Bar Cow/debian/");
    EXPECT_EQ("cdrom", U.Access);
@@ -111,6 +122,7 @@ TEST(URITest, RFC2732)
    EXPECT_EQ(0, U.Port);
    EXPECT_EQ("Foo Bar Cow", U.Host);
    EXPECT_EQ("/debian/", U.Path);
+   EXPECT_EQ("cdrom://Foo Bar Cow/debian/", (std::string)U);
    // percent encoded
    U = URI("ftp://foo:b%40r@example.org");
    EXPECT_EQ("foo", U.User);