This source file includes following definitions.
- IsString7Bit
- NextUtf8Sequence
- RunTest
- ConstructRepeatedTestString
- ConstructRangedTestString
- RunSomeTests
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
#include "base/i18n/streaming_utf8_validator.h"
#include <string>
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/test/perf_time_logger.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
namespace {
const char kOneByteSeqRangeStart[] = " ";
const char kOneByteSeqRangeEnd[] = "~";
const char kTwoByteSeqRangeStart[] = "\xc2\xa0";
const char kTwoByteSeqRangeEnd[] = "\xc9\x8f";
const char kThreeByteSeqRangeStart[] = "\xe3\x81\x82";
const char kThreeByteSeqRangeEnd[] = "\xe9\xbf\x83";
const char kFourByteSeqRangeStart[] = "\xf0\xa0\x80\x8b";
const char kFourByteSeqRangeEnd[] = "\xf0\xaa\x9a\xb2";
const size_t kTestLengths[] = {1, 32, 256, 32768, 1 << 20};
bool IsString7Bit(const std::string& s) {
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
if (*it & 0x80)
return false;
}
return true;
}
std::string NextUtf8Sequence(const std::string& previous) {
DCHECK(StreamingUtf8Validator::Validate(previous));
std::string next = previous;
for (int i = static_cast<int>(previous.length() - 1); i >= 0; --i) {
if (i > 0 && next[i] == '\xbf') {
next[i] = '\x80';
continue;
}
++next[i];
break;
}
DCHECK(StreamingUtf8Validator::Validate(next))
<< "Result \"" << next << "\" failed validation";
return next;
}
typedef bool (*TestTargetType)(const std::string&);
bool RunTest(const std::string& description,
TestTargetType target,
const std::string& test_string,
int times) {
base::PerfTimeLogger timer(description.c_str());
bool result = true;
for (int i = 0; i < times; ++i) {
result = target(test_string) && result;
}
timer.Done();
return result;
}
std::string ConstructRepeatedTestString(const std::string& input,
size_t length) {
std::string output = input;
while (output.length() * 2 < length) {
output += output;
}
if (output.length() < length) {
output += ConstructRepeatedTestString(input, length - output.length());
}
return output;
}
std::string ConstructRangedTestString(const std::string& input_start,
const std::string& input_end,
size_t length) {
std::string output = input_start;
std::string input = input_start;
while (output.length() < length && input != input_end) {
input = NextUtf8Sequence(input);
output += input;
}
if (output.length() < length) {
output = ConstructRepeatedTestString(output, length);
}
return output;
}
struct TestFunctionDescription {
TestTargetType function;
const char* function_name;
};
const TestFunctionDescription kTestFunctions[] = {
{&StreamingUtf8Validator::Validate, "StreamingUtf8Validator"},
{&IsStringUTF8, "IsStringUTF8"}, {&IsString7Bit, "IsString7Bit"}};
void RunSomeTests(
const char format[],
base::Callback<std::string(size_t length)> construct_test_string,
const TestFunctionDescription* test_functions,
size_t test_count) {
for (size_t i = 0; i < arraysize(kTestLengths); ++i) {
const size_t length = kTestLengths[i];
const std::string test_string = construct_test_string.Run(length);
const int real_length = static_cast<int>(test_string.length());
const int times = (1 << 24) / real_length;
for (size_t test_index = 0; test_index < test_count; ++test_index) {
EXPECT_TRUE(RunTest(StringPrintf(format,
test_functions[test_index].function_name,
real_length,
times),
test_functions[test_index].function,
test_string,
times));
}
}
}
TEST(StreamingUtf8ValidatorPerfTest, OneByteRepeated) {
RunSomeTests("%s: bytes=1 repeated length=%d repeat=%d",
base::Bind(ConstructRepeatedTestString, kOneByteSeqRangeStart),
kTestFunctions,
3);
}
TEST(StreamingUtf8ValidatorPerfTest, OneByteRange) {
RunSomeTests("%s: bytes=1 ranged length=%d repeat=%d",
base::Bind(ConstructRangedTestString,
kOneByteSeqRangeStart,
kOneByteSeqRangeEnd),
kTestFunctions,
3);
}
TEST(StreamingUtf8ValidatorPerfTest, TwoByteRepeated) {
RunSomeTests("%s: bytes=2 repeated length=%d repeat=%d",
base::Bind(ConstructRepeatedTestString, kTwoByteSeqRangeStart),
kTestFunctions,
2);
}
TEST(StreamingUtf8ValidatorPerfTest, TwoByteRange) {
RunSomeTests("%s: bytes=2 ranged length=%d repeat=%d",
base::Bind(ConstructRangedTestString,
kTwoByteSeqRangeStart,
kTwoByteSeqRangeEnd),
kTestFunctions,
2);
}
TEST(StreamingUtf8ValidatorPerfTest, ThreeByteRepeated) {
RunSomeTests(
"%s: bytes=3 repeated length=%d repeat=%d",
base::Bind(ConstructRepeatedTestString, kThreeByteSeqRangeStart),
kTestFunctions,
2);
}
TEST(StreamingUtf8ValidatorPerfTest, ThreeByteRange) {
RunSomeTests("%s: bytes=3 ranged length=%d repeat=%d",
base::Bind(ConstructRangedTestString,
kThreeByteSeqRangeStart,
kThreeByteSeqRangeEnd),
kTestFunctions,
2);
}
TEST(StreamingUtf8ValidatorPerfTest, FourByteRepeated) {
RunSomeTests("%s: bytes=4 repeated length=%d repeat=%d",
base::Bind(ConstructRepeatedTestString, kFourByteSeqRangeStart),
kTestFunctions,
2);
}
TEST(StreamingUtf8ValidatorPerfTest, FourByteRange) {
RunSomeTests("%s: bytes=4 ranged length=%d repeat=%d",
base::Bind(ConstructRangedTestString,
kFourByteSeqRangeStart,
kFourByteSeqRangeEnd),
kTestFunctions,
2);
}
}
}