Browse Source

ensure a good clock() value for usage and tests

We use clock() as a very cheap way of getting a "random" value, but the
manpage warns that this could return -1, so we should be dealing with
this. Additionally, e.g. on hurd-i386 the value increases only slowly –
to slow for our fast running tests for randomness hence producing the
same range in both samples, so we introduce a simple busy-wait loop (as
clock is counting processor time used by the program) in the test which
delays the second sample just enough making our randomness a bit more
predictable.
David Kalnischkies 7 years ago
parent
commit
379a36f43d
2 changed files with 10 additions and 2 deletions
  1. 1 1
      apt-pkg/contrib/srvrec.cc
  2. 9 1
      test/libapt/srvrecs_test.cc

+ 1 - 1
apt-pkg/contrib/srvrec.cc

@@ -185,7 +185,7 @@ SrvRec PopFromSrvRecs(std::vector<SrvRec> &Recs)
 	 [&I](SrvRec const &J) { return I->priority != J.priority; });
 
    // clock seems random enough.
-   I += clock() % std::distance(I, J);
+   I += std::max(static_cast<clock_t>(0), clock()) % std::distance(I, J);
    SrvRec const selected = std::move(*I);
    Recs.erase(I);
 

+ 9 - 1
test/libapt/srvrecs_test.cc

@@ -53,12 +53,19 @@ TEST(SrvRecTest,Randomness)
    EXPECT_EQ(testLength*2, base2.size());
 
    std::vector<SrvRec> first_pull;
+   auto const startingClock = clock();
    for (unsigned int i = 0; i < testLength; ++i)
       first_pull.push_back(PopFromSrvRecs(base1));
    EXPECT_TRUE(base1.empty());
    EXPECT_FALSE(first_pull.empty());
    EXPECT_EQ(testLength, first_pull.size());
 
+   // busy-wait for a cpu-clock change as we use it as "random" value
+   if (startingClock != -1)
+      for (int i = 0; i < 100000; ++i)
+	 if (startingClock != clock())
+	    break;
+
    std::vector<SrvRec> second_pull;
    for (unsigned int i = 0; i < testLength; ++i)
       second_pull.push_back(PopFromSrvRecs(base2));
@@ -69,7 +76,8 @@ TEST(SrvRecTest,Randomness)
    EXPECT_EQ(first_pull.size(), second_pull.size());
    EXPECT_TRUE(std::all_of(first_pull.begin(), first_pull.end(), [](SrvRec const &R) { return R.priority == 20; }));
    EXPECT_TRUE(std::all_of(second_pull.begin(), second_pull.end(), [](SrvRec const &R) { return R.priority == 20; }));
-   EXPECT_FALSE(std::equal(first_pull.begin(), first_pull.end(), second_pull.begin()));
+   if (startingClock != -1 && startingClock != clock())
+      EXPECT_FALSE(std::equal(first_pull.begin(), first_pull.end(), second_pull.begin()));
 
    EXPECT_TRUE(std::all_of(base2.begin(), base2.end(), [](SrvRec const &R) { return R.priority == 30; }));
 }