chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,451 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you 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 <gtest/gtest.h>
|
||||
#include "butil/string_splitter.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace {
|
||||
class StringSplitterTest : public ::testing::Test{
|
||||
protected:
|
||||
StringSplitterTest(){};
|
||||
virtual ~StringSplitterTest(){};
|
||||
virtual void SetUp() {
|
||||
srand (time(0));
|
||||
};
|
||||
virtual void TearDown() {
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
TEST_F(StringSplitterTest, sanity) {
|
||||
const char* str = "hello there! man ";
|
||||
butil::StringSplitter ss(str, ' ');
|
||||
// "hello"
|
||||
ASSERT_TRUE(ss != NULL);
|
||||
ASSERT_EQ(5ul, ss.length());
|
||||
ASSERT_EQ(ss.field(), str);
|
||||
|
||||
// "there!"
|
||||
++ss;
|
||||
ASSERT_NE(ss, (void*)NULL);
|
||||
ASSERT_EQ(6ul, ss.length());
|
||||
ASSERT_EQ(ss.field(), str+6);
|
||||
|
||||
// "man"
|
||||
++ss;
|
||||
ASSERT_TRUE(ss);
|
||||
ASSERT_EQ(3ul, ss.length());
|
||||
ASSERT_EQ(ss.field(), str+15);
|
||||
|
||||
++ss;
|
||||
ASSERT_FALSE(ss);
|
||||
ASSERT_EQ(0ul, ss.length());
|
||||
ASSERT_EQ(ss.field(), str + strlen(str));
|
||||
|
||||
// consecutive separators are treated as zero-length field inside
|
||||
butil::StringSplitter ss2(str, ' ', butil::ALLOW_EMPTY_FIELD);
|
||||
|
||||
// "hello"
|
||||
ASSERT_TRUE(ss2);
|
||||
ASSERT_EQ(5ul, ss2.length());
|
||||
ASSERT_FALSE(strncmp(ss2.field(), "hello", ss2.length()));
|
||||
|
||||
// "there!"
|
||||
++ss2;
|
||||
ASSERT_TRUE(ss2);
|
||||
ASSERT_EQ(6ul, ss2.length());
|
||||
ASSERT_FALSE(strncmp(ss2.field(), "there!", ss2.length()));
|
||||
|
||||
// ""
|
||||
++ss2;
|
||||
ASSERT_TRUE(ss2);
|
||||
ASSERT_EQ(0ul, ss2.length());
|
||||
ASSERT_EQ(ss2.field(), str+13);
|
||||
|
||||
// ""
|
||||
++ss2;
|
||||
ASSERT_TRUE(ss2);
|
||||
ASSERT_EQ(0ul, ss2.length());
|
||||
ASSERT_EQ(ss2.field(), str+14);
|
||||
|
||||
// "man"
|
||||
++ss2;
|
||||
ASSERT_TRUE(ss2);
|
||||
ASSERT_EQ(3ul, ss2.length());
|
||||
ASSERT_EQ(ss2.field(), str+15);
|
||||
|
||||
++ss2;
|
||||
ASSERT_FALSE(ss2);
|
||||
ASSERT_EQ(0ul, ss2.length());
|
||||
ASSERT_EQ(ss2.field(), str+19);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(StringSplitterTest, single_word)
|
||||
{
|
||||
const char* str = "apple";
|
||||
butil::StringSplitter ss(str, ' ');
|
||||
// "apple"
|
||||
ASSERT_TRUE(ss);
|
||||
ASSERT_EQ(5ul, ss.length());
|
||||
ASSERT_EQ(ss.field(), str);
|
||||
|
||||
++ss;
|
||||
ASSERT_FALSE(ss);
|
||||
ASSERT_EQ(0ul, ss.length());
|
||||
ASSERT_EQ(ss.field(), str+5);
|
||||
}
|
||||
|
||||
TEST_F(StringSplitterTest, starting_with_separator) {
|
||||
const char* str = " apple";
|
||||
butil::StringSplitter ss(str, ' ');
|
||||
// "apple"
|
||||
ASSERT_TRUE(ss);
|
||||
ASSERT_EQ(5ul, ss.length());
|
||||
ASSERT_FALSE(strncmp(ss.field(), "apple", ss.length()));
|
||||
|
||||
++ss;
|
||||
ASSERT_FALSE(ss);
|
||||
ASSERT_EQ(0ul, ss.length());
|
||||
ASSERT_EQ(ss.field(), str + strlen(str));
|
||||
|
||||
butil::StringSplitter ss2(str, ' ', butil::ALLOW_EMPTY_FIELD);
|
||||
// ""
|
||||
ASSERT_TRUE(ss2);
|
||||
ASSERT_EQ(0ul, ss2.length());
|
||||
ASSERT_EQ(ss2.field(), str);
|
||||
|
||||
// ""
|
||||
++ss2;
|
||||
ASSERT_TRUE(ss2);
|
||||
ASSERT_EQ(0ul, ss2.length());
|
||||
ASSERT_EQ(ss2.field(), str+1);
|
||||
|
||||
// "apple"
|
||||
++ss2;
|
||||
ASSERT_TRUE(ss2);
|
||||
ASSERT_EQ(5ul, ss2.length());
|
||||
ASSERT_FALSE(strncmp(ss2.field(), "apple", ss2.length()));
|
||||
|
||||
++ss2;
|
||||
ASSERT_FALSE(ss2);
|
||||
ASSERT_EQ(0ul, ss2.length());
|
||||
ASSERT_EQ(ss2.field(), str + strlen(str));
|
||||
}
|
||||
|
||||
TEST_F(StringSplitterTest, site_id_as_example) {
|
||||
const char* str = "|123|12||1|21|4321";
|
||||
butil::StringSplitter ss(str, '|');
|
||||
ASSERT_TRUE(ss);
|
||||
ASSERT_EQ(3ul, ss.length());
|
||||
ASSERT_FALSE(strncmp(ss.field(), "123", ss.length()));
|
||||
|
||||
ss++;
|
||||
ASSERT_TRUE(ss);
|
||||
ASSERT_EQ(2ul, ss.length());
|
||||
ASSERT_FALSE(strncmp(ss.field(), "12", ss.length()));
|
||||
|
||||
ss++;
|
||||
ASSERT_TRUE(ss);
|
||||
ASSERT_EQ(1ul, ss.length());
|
||||
ASSERT_FALSE(strncmp(ss.field(), "1", ss.length()));
|
||||
|
||||
ss++;
|
||||
ASSERT_TRUE(ss);
|
||||
ASSERT_EQ(2ul, ss.length());
|
||||
ASSERT_FALSE(strncmp(ss.field(), "21", ss.length()));
|
||||
|
||||
ss++;
|
||||
ASSERT_TRUE(ss);
|
||||
ASSERT_EQ(4ul, ss.length());
|
||||
ASSERT_FALSE(strncmp(ss.field(), "4321", ss.length()));
|
||||
|
||||
++ss;
|
||||
ASSERT_FALSE(ss);
|
||||
ASSERT_EQ(0ul, ss.length());
|
||||
ASSERT_EQ(ss.field(), str + strlen(str));
|
||||
}
|
||||
|
||||
TEST_F(StringSplitterTest, number_list) {
|
||||
const char* str = " 123,,12,1, 21 4321\00056";
|
||||
butil::StringMultiSplitter ss(str, ", ");
|
||||
ASSERT_TRUE(ss);
|
||||
ASSERT_EQ(3ul, ss.length());
|
||||
ASSERT_FALSE(strncmp(ss.field(), "123", ss.length()));
|
||||
|
||||
ss++;
|
||||
ASSERT_TRUE(ss);
|
||||
ASSERT_EQ(2ul, ss.length());
|
||||
ASSERT_FALSE(strncmp(ss.field(), "12", ss.length()));
|
||||
|
||||
ss++;
|
||||
ASSERT_TRUE(ss);
|
||||
ASSERT_EQ(1ul, ss.length());
|
||||
ASSERT_FALSE(strncmp(ss.field(), "1", ss.length()));
|
||||
|
||||
ss++;
|
||||
ASSERT_TRUE(ss);
|
||||
ASSERT_EQ(2ul, ss.length());
|
||||
ASSERT_FALSE(strncmp(ss.field(), "21", ss.length()));
|
||||
|
||||
ss++;
|
||||
ASSERT_TRUE(ss);
|
||||
ASSERT_EQ(4ul, ss.length());
|
||||
ASSERT_FALSE(strncmp(ss.field(), "4321", ss.length()));
|
||||
|
||||
++ss;
|
||||
ASSERT_FALSE(ss);
|
||||
ASSERT_EQ(0ul, ss.length());
|
||||
ASSERT_EQ(ss.field(), str + strlen(str));
|
||||
|
||||
// contains embedded '\0'
|
||||
const size_t str_len = 23;
|
||||
butil::StringMultiSplitter ss2(str, str + str_len, ", ");
|
||||
ASSERT_TRUE(ss2);
|
||||
ASSERT_EQ(3ul, ss2.length());
|
||||
ASSERT_FALSE(strncmp(ss2.field(), "123", ss2.length()));
|
||||
|
||||
ss2++;
|
||||
ASSERT_TRUE(ss2);
|
||||
ASSERT_EQ(2ul, ss2.length());
|
||||
ASSERT_FALSE(strncmp(ss2.field(), "12", ss2.length()));
|
||||
|
||||
ss2++;
|
||||
ASSERT_TRUE(ss2);
|
||||
ASSERT_EQ(1ul, ss2.length());
|
||||
ASSERT_FALSE(strncmp(ss2.field(), "1", ss2.length()));
|
||||
|
||||
ss2++;
|
||||
ASSERT_TRUE(ss2);
|
||||
ASSERT_EQ(2ul, ss2.length());
|
||||
ASSERT_FALSE(strncmp(ss2.field(), "21", ss2.length()));
|
||||
|
||||
ss2++;
|
||||
ASSERT_TRUE(ss2);
|
||||
ASSERT_EQ(7ul, ss2.length());
|
||||
ASSERT_FALSE(strncmp(ss2.field(), "4321\00056", ss2.length()));
|
||||
|
||||
++ss2;
|
||||
ASSERT_FALSE(ss2);
|
||||
ASSERT_EQ(0ul, ss2.length());
|
||||
ASSERT_EQ(ss2.field(), str + str_len);
|
||||
}
|
||||
|
||||
TEST_F(StringSplitterTest, cast_type) {
|
||||
const char* str = "-1\t123\t111\t1\t10\t11\t1.3\t3.1415926\t127\t128\t256";
|
||||
int i = 0;
|
||||
unsigned int u = 0;
|
||||
long l = 0;
|
||||
unsigned long ul = 0;
|
||||
long long ll = 0;
|
||||
unsigned long long ull = 0;
|
||||
float f = 0.0;
|
||||
double d = 0.0;
|
||||
|
||||
butil::StringSplitter ss(str, '\t');
|
||||
ASSERT_TRUE(ss);
|
||||
|
||||
ASSERT_EQ(0, ss.to_int(&i));
|
||||
ASSERT_EQ(-1, i);
|
||||
|
||||
ASSERT_TRUE(++ss);
|
||||
ASSERT_EQ(0, ss.to_uint(&u));
|
||||
ASSERT_EQ(123u, u);
|
||||
|
||||
ASSERT_TRUE(++ss);
|
||||
ASSERT_EQ(0, ss.to_long(&l));
|
||||
ASSERT_EQ(111, l);
|
||||
|
||||
|
||||
ASSERT_TRUE(++ss);
|
||||
ASSERT_EQ(0, ss.to_ulong(&ul));
|
||||
ASSERT_EQ(1ul, ul);
|
||||
|
||||
ASSERT_TRUE(++ss);
|
||||
ASSERT_EQ(0, ss.to_longlong(&ll));
|
||||
ASSERT_EQ(10, ll);
|
||||
|
||||
ASSERT_TRUE(++ss);
|
||||
ASSERT_EQ(0, ss.to_ulonglong(&ull));
|
||||
ASSERT_EQ(11ull, ull);
|
||||
|
||||
ASSERT_TRUE(++ss);
|
||||
ASSERT_EQ(0, ss.to_float(&f));
|
||||
ASSERT_FLOAT_EQ(1.3, f);
|
||||
|
||||
ASSERT_TRUE(++ss);
|
||||
ASSERT_EQ(0, ss.to_double(&d));
|
||||
ASSERT_DOUBLE_EQ(3.1415926, d);
|
||||
|
||||
ASSERT_TRUE(++ss);
|
||||
int8_t c = 0;
|
||||
ASSERT_EQ(0, ss.to_int8(&c));
|
||||
ASSERT_EQ(127, c);
|
||||
|
||||
ASSERT_TRUE(++ss);
|
||||
uint8_t uc = 0;
|
||||
ASSERT_EQ(0, ss.to_uint8(&uc));
|
||||
ASSERT_EQ(128U, uc);
|
||||
|
||||
ASSERT_TRUE(++ss);
|
||||
ASSERT_EQ(-1, ss.to_uint8(&uc));
|
||||
}
|
||||
|
||||
TEST_F(StringSplitterTest, split_limit_len) {
|
||||
const char* str = "1\t1\0003\t111\t1\t10\t11\t1.3\t3.1415926";
|
||||
butil::StringSplitter ss(str, str + 5, '\t');
|
||||
|
||||
ASSERT_TRUE(ss);
|
||||
ASSERT_EQ(1ul, ss.length());
|
||||
ASSERT_FALSE(strncmp(ss.field(), "1", ss.length()));
|
||||
|
||||
++ss;
|
||||
ASSERT_TRUE(ss);
|
||||
ASSERT_EQ(3ul, ss.length());
|
||||
ASSERT_FALSE(strncmp(ss.field(), "1\0003", ss.length()));
|
||||
|
||||
++ss;
|
||||
ASSERT_FALSE(ss);
|
||||
|
||||
// Allows using '\0' as separator
|
||||
butil::StringSplitter ss2(str, str + 5, '\0');
|
||||
|
||||
ASSERT_TRUE(ss2);
|
||||
ASSERT_EQ(3ul, ss2.length());
|
||||
ASSERT_FALSE(strncmp(ss2.field(), "1\t1", ss2.length()));
|
||||
|
||||
++ss2;
|
||||
ASSERT_TRUE(ss2);
|
||||
ASSERT_EQ(1ul, ss2.length());
|
||||
ASSERT_FALSE(strncmp(ss2.field(), "3", ss2.length()));
|
||||
|
||||
++ss2;
|
||||
ASSERT_FALSE(ss2);
|
||||
|
||||
butil::StringPiece sp(str, 5);
|
||||
// Allows using '\0' as separator
|
||||
butil::StringSplitter ss3(sp, '\0');
|
||||
|
||||
ASSERT_TRUE(ss3);
|
||||
ASSERT_EQ(3ul, ss3.length());
|
||||
ASSERT_FALSE(strncmp(ss3.field(), "1\t1", ss3.length()));
|
||||
|
||||
++ss3;
|
||||
ASSERT_TRUE(ss3);
|
||||
ASSERT_EQ(1ul, ss3.length());
|
||||
ASSERT_FALSE(strncmp(ss3.field(), "3", ss3.length()));
|
||||
|
||||
++ss3;
|
||||
ASSERT_FALSE(ss3);
|
||||
}
|
||||
|
||||
TEST_F(StringSplitterTest, non_null_terminated_string) {
|
||||
const char str[] = " a non null terminated string ";
|
||||
const size_t len = strlen(str);
|
||||
char* buf = new char[len];
|
||||
memcpy(buf, str, len);
|
||||
|
||||
butil::StringSplitter ss(buf, buf + len, ' ');
|
||||
|
||||
// "a"
|
||||
ASSERT_TRUE(ss != NULL);
|
||||
ASSERT_EQ(1ul, ss.length());
|
||||
ASSERT_EQ(ss.field(), buf + 2);
|
||||
|
||||
// "non"
|
||||
++ss;
|
||||
ASSERT_TRUE(ss != NULL);
|
||||
ASSERT_EQ(3ul, ss.length());
|
||||
ASSERT_EQ(ss.field(), buf + 4);
|
||||
|
||||
// "null"
|
||||
++ss;
|
||||
ASSERT_TRUE(ss != NULL);
|
||||
ASSERT_EQ(4ul, ss.length());
|
||||
ASSERT_EQ(ss.field(), buf + 9);
|
||||
|
||||
// "terminated"
|
||||
++ss;
|
||||
ASSERT_TRUE(ss != NULL);
|
||||
ASSERT_EQ(10ul, ss.length());
|
||||
ASSERT_EQ(ss.field(), buf + 16);
|
||||
|
||||
// "string"
|
||||
++ss;
|
||||
ASSERT_TRUE(ss != NULL);
|
||||
ASSERT_EQ(6ul, ss.length());
|
||||
ASSERT_EQ(ss.field(), buf + 28);
|
||||
|
||||
++ss;
|
||||
ASSERT_FALSE(ss);
|
||||
ASSERT_EQ(0ul, ss.length());
|
||||
ASSERT_EQ(ss.field(), buf + len);
|
||||
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
TEST_F(StringSplitterTest, key_value_pairs_splitter_sanity) {
|
||||
std::string kvstr = "key1=value1&&&key2=value2&key3=value3&===&key4=&=&=value5";
|
||||
for (int i = 0 ; i < 3; ++i) {
|
||||
// Test three constructors
|
||||
butil::KeyValuePairsSplitter* psplitter = NULL;
|
||||
if (i == 0) {
|
||||
psplitter = new butil::KeyValuePairsSplitter(kvstr, '&', '=');
|
||||
} else if (i == 1) {
|
||||
psplitter = new butil::KeyValuePairsSplitter(
|
||||
kvstr.data(), kvstr.data() + kvstr.size(), '&', '=');
|
||||
} else if (i == 2) {
|
||||
psplitter = new butil::KeyValuePairsSplitter(kvstr.c_str(), '&', '=');
|
||||
}
|
||||
butil::KeyValuePairsSplitter& splitter = *psplitter;
|
||||
|
||||
ASSERT_TRUE(splitter);
|
||||
ASSERT_EQ(splitter.key(), "key1");
|
||||
ASSERT_EQ(splitter.value(), "value1");
|
||||
++splitter;
|
||||
ASSERT_TRUE(splitter);
|
||||
ASSERT_EQ(splitter.key(), "key2");
|
||||
ASSERT_EQ(splitter.value(), "value2");
|
||||
++splitter;
|
||||
ASSERT_TRUE(splitter);
|
||||
ASSERT_EQ(splitter.key(), "key3");
|
||||
ASSERT_EQ(splitter.value(), "value3");
|
||||
++splitter;
|
||||
ASSERT_TRUE(splitter);
|
||||
ASSERT_EQ(splitter.key(), "");
|
||||
ASSERT_EQ(splitter.value(), "==");
|
||||
++splitter;
|
||||
ASSERT_TRUE(splitter);
|
||||
ASSERT_EQ(splitter.key(), "key4");
|
||||
ASSERT_EQ(splitter.value(), "");
|
||||
++splitter;
|
||||
ASSERT_TRUE(splitter);
|
||||
ASSERT_EQ(splitter.key(), "");
|
||||
ASSERT_EQ(splitter.value(), "");
|
||||
++splitter;
|
||||
ASSERT_TRUE(splitter);
|
||||
ASSERT_EQ(splitter.key(), "");
|
||||
ASSERT_EQ(splitter.value(), "value5");
|
||||
++splitter;
|
||||
ASSERT_FALSE(splitter);
|
||||
|
||||
delete psplitter;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user