blob: 9d3bffb17aaada2cb4496597791406ca068f8176 [file] [log] [blame]
// 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 "runtime/string-search.h"
namespace impala {
StringValue StrValFromCString(const char* str, int len) {
if (len == -1) len = strlen(str);
return StringValue(const_cast<char*>(str), len);
}
// Test string search for haystack/needle, up to len for each.
// If the length is -1, use the full string length.
// Searching in a substring allows checking whether the search respects the
// length stored in the StringValue or also reads parts of the string which
// should be excluded.
int TestSearch(const char* haystack, const char* needle, int haystack_len = -1,
int needle_len = -1) {
StringValue needle_str_val = StrValFromCString(needle, needle_len);
StringValue haystack_str_val = StrValFromCString(haystack, haystack_len);
StringSearch search(&needle_str_val);
return search.Search(&haystack_str_val);
}
// Test reverse string search for haystack/needle, up to len for each.
// If the length is -1, use the full string length.
// Searching in a substring allows checking whether the search respects the
// length stored in the StringValue or also reads parts of the string which
// should be excluded.
int TestRSearch(const char* haystack, const char* needle, int haystack_len = -1,
int needle_len = -1) {
StringValue needle_str_val = StrValFromCString(needle, needle_len);
StringValue haystack_str_val = StrValFromCString(haystack, haystack_len);
StringSearch search(&needle_str_val);
return search.RSearch(&haystack_str_val);
}
TEST(StringSearchTest, RegularSearch) {
// Basic Tests
EXPECT_EQ(0, TestSearch("abcdabcd", "a"));
EXPECT_EQ(0, TestSearch("abcdabcd", "ab"));
EXPECT_EQ(2, TestSearch("abcdabcd", "c"));
EXPECT_EQ(2, TestSearch("abcdabcd", "cd"));
EXPECT_EQ(-1, TestSearch("", ""));
EXPECT_EQ(-1, TestSearch("abc", ""));
EXPECT_EQ(-1, TestSearch("", "a"));
// Test single chars
EXPECT_EQ(0, TestSearch("a", "a"));
EXPECT_EQ(-1, TestSearch("a", "b"));
EXPECT_EQ(1, TestSearch("abc", "b"));
// Test searching in a substring of the haystack
EXPECT_EQ(0, TestSearch("abcabcd", "abc", 5));
EXPECT_EQ(-1, TestSearch("abcabcd", "abcd", 5));
EXPECT_EQ(-1, TestSearch("abcabcd", "abcd", 0));
// Test searching a substring of the needle in a substring of the haystack.
EXPECT_EQ(0, TestSearch("abcde", "abaaaaaa", 4, 2));
EXPECT_EQ(-1, TestSearch("abcde", "abaaaaaa", 4, 3));
EXPECT_EQ(-1, TestSearch("abcdabaaaaa", "abaaaaaa", 4, 3));
EXPECT_EQ(-1, TestSearch("abcdabaaaaa", "abaaaaaa", 4, 0));
EXPECT_EQ(-1, TestSearch("abcdabaaaaa", "abaaaaaa"));
// Test with needle matching the end of the substring.
EXPECT_EQ(4, TestSearch("abcde", "e"));
EXPECT_EQ(3, TestSearch("abcde", "de"));
EXPECT_EQ(2, TestSearch("abcdede", "cde"));
EXPECT_EQ(5, TestSearch("abcdacde", "cde"));
// Test correct skip_ handling, which depends on which char of the needle is
// the same as the last one.
EXPECT_EQ(2, TestSearch("ababcacac", "abcacac"));
}
TEST(StringSearchTest, ReverseSearch) {
// Basic Tests
EXPECT_EQ(4, TestRSearch("abcdabcd", "a"));
EXPECT_EQ(4, TestRSearch("abcdabcd", "ab"));
EXPECT_EQ(6, TestRSearch("abcdabcd", "c"));
EXPECT_EQ(6, TestRSearch("abcdabcd", "cd"));
EXPECT_EQ(-1, TestRSearch("", ""));
EXPECT_EQ(-1, TestRSearch("abc", ""));
EXPECT_EQ(-1, TestRSearch("", "a"));
// Test single chars
EXPECT_EQ(0, TestRSearch("a", "a"));
EXPECT_EQ(-1, TestRSearch("a", "b"));
EXPECT_EQ(1, TestRSearch("abc", "b"));
// Test searching in a substring of the haystack
EXPECT_EQ(0, TestRSearch("abcabcd", "abc", 5));
EXPECT_EQ(-1, TestRSearch("abcabcd", "abcd", 5));
EXPECT_EQ(-1, TestRSearch("abcabcd", "abcd", 0));
// Test searching a substring of the needle in a substring of the haystack.
EXPECT_EQ(0, TestRSearch("abcde", "abaaaaaa", 4, 2));
EXPECT_EQ(-1, TestRSearch("abcde", "abaaaaaa", 4, 3));
EXPECT_EQ(-1, TestRSearch("abcdabaaaaa", "abaaaaaa", 4, 3));
EXPECT_EQ(-1, TestRSearch("abcdabaaaaa", "abaaaaaa", 4, 0));
EXPECT_EQ(-1, TestRSearch("abcdabaaaaa", "abaaaaaa"));
// Test with needle matching the end of the substring.
EXPECT_EQ(4, TestRSearch("abcde", "e"));
EXPECT_EQ(3, TestRSearch("abcde", "de"));
EXPECT_EQ(2, TestRSearch("abcdede", "cde"));
EXPECT_EQ(5, TestRSearch("abcdacde", "cde"));
// Test correct rskip_ handling, which depends on which char of the needle is
// the same as the first one.
EXPECT_EQ(0, TestRSearch("cacacbaba", "cacacba"));
}
}