blob: 4c37d7f2ad6e903b4aabb6a13067e5ad8eaea137 [file] [log] [blame]
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Author: jmaessen@google.com (Jan Maessen)
// Unit-test the statistics work bound.
#include "pagespeed/kernel/util/statistics_work_bound.h"
#include "base/logging.h"
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/statistics_template.h"
#include "pagespeed/kernel/base/thread_system.h"
#include "pagespeed/kernel/util/platform.h"
#include "pagespeed/kernel/util/simple_stats.h"
namespace net_instaweb {
class UpDownCounter;
namespace {
class StatisticsWorkBoundTest : public testing::Test {
public:
StatisticsWorkBoundTest()
: thread_system_(Platform::CreateThreadSystem()),
stats_(thread_system_.get()),
var1_(stats_.AddUpDownCounter("var1")),
var2_(stats_.AddUpDownCounter("var2")) { }
protected:
scoped_ptr<ThreadSystem> thread_system_;
SimpleStats stats_;
UpDownCounter* var1_;
UpDownCounter* var2_;
StatisticsWorkBound* MakeBound(UpDownCounter* var, int bound) {
StatisticsWorkBound* result = new StatisticsWorkBound(var, bound);
CHECK(NULL != result);
return result;
}
private:
DISALLOW_COPY_AND_ASSIGN(StatisticsWorkBoundTest);
};
// Test with a bound of two.
TEST_F(StatisticsWorkBoundTest, TestTwoBound) {
// We allocate two objects backed by the same statistic,
// to ensure that they share a common count. This is what
// happens in a multi-process setting.
scoped_ptr<StatisticsWorkBound> bound1(MakeBound(var1_, 2));
scoped_ptr<StatisticsWorkBound> bound2(MakeBound(var1_, 2));
// Repeat twice to ensure that we actually made it back to 0.
for (int i = 0; i < 2; i++) {
// Start with no workers.
EXPECT_TRUE(bound1->TryToWork());
// One worker here.
EXPECT_TRUE(bound1->TryToWork());
EXPECT_FALSE(bound1->TryToWork());
EXPECT_FALSE(bound2->TryToWork());
bound1->WorkComplete();
// One worker here.
EXPECT_TRUE(bound2->TryToWork());
EXPECT_FALSE(bound1->TryToWork());
EXPECT_FALSE(bound2->TryToWork());
bound1->WorkComplete();
// Back to one worker.
EXPECT_TRUE(bound2->TryToWork());
EXPECT_FALSE(bound1->TryToWork());
EXPECT_FALSE(bound2->TryToWork());
bound2->WorkComplete();
// Back to one worker.
bound2->WorkComplete();
// Back to none.
}
}
// Test that a bound of 0 allows large # of tries.
TEST_F(StatisticsWorkBoundTest, TestZeroBound) {
scoped_ptr<StatisticsWorkBound> bound1(MakeBound(var1_, 0));
scoped_ptr<StatisticsWorkBound> bound2(MakeBound(var1_, 0));
for (int i = 0; i < 1000; ++i) {
EXPECT_TRUE(bound1->TryToWork());
EXPECT_TRUE(bound2->TryToWork());
}
}
// Test that a bound of -1 allows large # of tries.
TEST_F(StatisticsWorkBoundTest, TestNegativeBound) {
scoped_ptr<StatisticsWorkBound> bound1(MakeBound(var1_, -1));
scoped_ptr<StatisticsWorkBound> bound2(MakeBound(var1_, -1));
for (int i = 0; i < 1000; ++i) {
EXPECT_TRUE(bound1->TryToWork());
EXPECT_TRUE(bound2->TryToWork());
}
}
// Test that absent variable allows large # of tries.
TEST_F(StatisticsWorkBoundTest, TestNullVar) {
scoped_ptr<StatisticsWorkBound> bound1(MakeBound(NULL, 2));
scoped_ptr<StatisticsWorkBound> bound2(MakeBound(NULL, 2));
for (int i = 0; i < 1000; ++i) {
EXPECT_TRUE(bound1->TryToWork());
EXPECT_TRUE(bound2->TryToWork());
}
}
// Test that differently-named bounds are distinct
TEST_F(StatisticsWorkBoundTest, TestDistinctVar) {
scoped_ptr<StatisticsWorkBound> bound1(MakeBound(var1_, 2));
scoped_ptr<StatisticsWorkBound> bound2(MakeBound(var2_, 2));
EXPECT_TRUE(bound1->TryToWork());
EXPECT_TRUE(bound1->TryToWork());
EXPECT_FALSE(bound1->TryToWork());
EXPECT_TRUE(bound2->TryToWork());
EXPECT_TRUE(bound2->TryToWork());
EXPECT_FALSE(bound2->TryToWork());
bound1->WorkComplete();
EXPECT_FALSE(bound2->TryToWork());
EXPECT_TRUE(bound1->TryToWork());
}
} // namespace
} // namespace net_instaweb