blob: b49d0ade2dbe9fc51a2b412f6b93339fbd141e35 [file] [log] [blame]
// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// 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.
#include "cobalt/browser/memory_tracker/tool/util.h"
#include <string>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "nb/bit_cast.h"
#include "starboard/types.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cobalt {
namespace browser {
namespace memory_tracker {
namespace {
const char* ToAddress(uintptr_t val) { return nb::bit_cast<const char*>(val); }
// 4k page size.
static const uintptr_t kPageSize = 4096;
class FakeTimeSource {
public:
explicit FakeTimeSource(base::TimeTicks value) : static_time_(value) {}
void set_static_time(base::TimeTicks value) { static_time_ = value; }
base::TimeTicks GetTime() { return static_time_; }
private:
base::TimeTicks static_time_;
};
} // namespace.
// Tests the expectation that AllocationSizeBinner will correctly bin
// allocations.
TEST(UtilTest, RemoveString) {
std::string value = "abba";
value = RemoveString(value, "bb");
EXPECT_STREQ("aa", value.c_str());
}
// Tests the expectation that AllocationSizeBinner will correctly bin
// allocations.
TEST(UtilTest, InsertCommasIntoNumberString) {
std::string value = "2345.54";
std::string value_with_commas = InsertCommasIntoNumberString(value);
EXPECT_STREQ("2,345.54", value_with_commas.c_str());
}
TEST(UtilTest, NumberFormatWithCommas) {
int value = 1000;
std::string value_with_commas = NumberFormatWithCommas<int>(value);
EXPECT_STREQ("1,000", value_with_commas.c_str());
}
// Tests the expectation that RemoveOddElements() removes the odd elements of
// a vector and resizes it.
TEST(UtilTest, RemoveOddElements) {
std::vector<int> values;
// EVEN TEST.
values.push_back(0);
values.push_back(1);
values.push_back(2);
values.push_back(3);
RemoveOddElements(&values);
ASSERT_EQ(2, values.size());
EXPECT_EQ(0, values[0]);
EXPECT_EQ(2, values[1]);
values.clear();
// ODD TEST
values.push_back(0);
values.push_back(1);
values.push_back(2);
values.push_back(3);
values.push_back(4);
RemoveOddElements(&values);
ASSERT_EQ(3, values.size());
EXPECT_EQ(0, values[0]);
EXPECT_EQ(2, values[1]);
EXPECT_EQ(4, values[2]);
}
// Tests the expectation that GetLinearFit() generates the expected linear
// regression values.
TEST(UtilTest, GetLinearFit) {
std::vector<std::pair<int, int> > data;
for (int i = 0; i < 10; ++i) {
data.push_back(std::pair<int, int>(i + 1, 2 * i));
}
double slope = 0;
double y_intercept = 0;
GetLinearFit(data.begin(), data.end(), &slope, &y_intercept);
EXPECT_DOUBLE_EQ(2.0f, slope);
EXPECT_DOUBLE_EQ(-2.0f, y_intercept);
}
// Test the expectation that BaseNameFast() works correctly for both windows
// and linux path types.
TEST(UtilTest, BaseNameFast) {
const char* linux_path = "directory/filename.cc";
const char* win_path = "directory\\filename.cc";
EXPECT_STREQ("filename.cc", BaseNameFast(linux_path));
EXPECT_STREQ("filename.cc", BaseNameFast(win_path));
}
TEST(UtilTest, TimerUse) {
base::TimeTicks initial_time = base::TimeTicks::Now();
FakeTimeSource time_source(initial_time);
Timer::TimeFunctor time_functor =
base::Bind(&FakeTimeSource::GetTime, base::Unretained(&time_source));
Timer test_timer(base::TimeDelta::FromSeconds(30), time_functor);
EXPECT_FALSE(test_timer.UpdateAndIsExpired()); // 0 time has elapsed.
time_source.set_static_time(initial_time + base::TimeDelta::FromSeconds(29));
// 29 seconds has elapsed, which is less than the 30 seconds required for
// the timer to fire.
EXPECT_FALSE(test_timer.UpdateAndIsExpired());
time_source.set_static_time(initial_time + base::TimeDelta::FromSeconds(30));
// 31 seconds has elapsed, which means that the next call to
// UpdateAndIsExpired() should succeed.
EXPECT_TRUE(test_timer.UpdateAndIsExpired());
// Now that the value fired, expect that it won't fire again (until the next
// 30 seconds has passed).
EXPECT_FALSE(test_timer.UpdateAndIsExpired());
time_source.set_static_time(initial_time + base::TimeDelta::FromSeconds(60));
EXPECT_TRUE(test_timer.UpdateAndIsExpired());
EXPECT_FALSE(test_timer.UpdateAndIsExpired());
}
TEST(Segment, SplitAcrossPageBoundaries_Simple) {
std::string name("AllocName");
const char* start_addr = ToAddress(0);
const char* end_addr = ToAddress(1);
Segment memory_segment(&name, start_addr, end_addr);
std::vector<Segment> segments;
memory_segment.SplitAcrossPageBoundaries(kPageSize, &segments);
ASSERT_EQ(1, segments.size());
ASSERT_EQ(memory_segment, segments[0]);
}
TEST(Segment, SplitAcrossPageBoundaries_WholePage) {
std::string name("AllocName");
const char* start_addr = ToAddress(0);
const char* end_addr = ToAddress(kPageSize);
Segment memory_segment(&name, start_addr, end_addr);
std::vector<Segment> segments;
memory_segment.SplitAcrossPageBoundaries(kPageSize, &segments);
ASSERT_EQ(1, segments.size());
ASSERT_EQ(memory_segment, segments[0]);
}
TEST(Segment, SplitAcrossPageBoundaries_Across) {
std::string name("AllocName");
const char* start_addr = ToAddress(kPageSize / 2);
const char* mid_addr = ToAddress(kPageSize);
const char* end_addr = ToAddress(kPageSize + kPageSize / 2);
Segment memory_segment(&name, start_addr, end_addr);
std::vector<Segment> segments;
memory_segment.SplitAcrossPageBoundaries(kPageSize, &segments);
ASSERT_EQ(2, segments.size());
Segment s1(&name, start_addr, mid_addr);
Segment s2(&name, mid_addr, end_addr);
ASSERT_EQ(s1, segments[0]);
ASSERT_EQ(s2, segments[1]);
}
TEST(Segment, SplitAcrossPageBoundaries_Many) {
std::string name("AllocName");
const char* start_addr = ToAddress(kPageSize / 2);
const char* mid_0_addr = ToAddress(kPageSize);
const char* mid_1_addr = ToAddress(kPageSize * 2);
const char* end_addr = ToAddress(2 * kPageSize + kPageSize / 2);
Segment memory_segment(&name, start_addr, end_addr);
std::vector<Segment> segments;
memory_segment.SplitAcrossPageBoundaries(4096, &segments);
ASSERT_EQ(3, segments.size());
Segment s1(&name, start_addr, mid_0_addr);
Segment s2(&name, mid_0_addr, mid_1_addr);
Segment s3(&name, mid_1_addr, end_addr);
ASSERT_EQ(s1, segments[0]);
ASSERT_EQ(s2, segments[1]);
ASSERT_EQ(s3, segments[2]);
}
} // namespace memory_tracker
} // namespace browser
} // namespace cobalt