/* * Copyright (c) 2015, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Intel Corporation nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "gtest/gtest.h" #include "util/charreach.h" using namespace ue2; TEST(ng_charreach, init) { CharReach cr; ASSERT_EQ(0U, cr.count()); ASSERT_TRUE(cr.none()); ASSERT_FALSE(cr.all()); ASSERT_EQ(256U, cr.size()); } TEST(ng_charreach, set) { CharReach cr; ASSERT_EQ(0U, cr.count()); ASSERT_TRUE(cr.none()); ASSERT_FALSE(cr.all()); cr.set('q'); ASSERT_EQ(1U, cr.count()); cr.setall(); ASSERT_EQ(cr.size(), cr.count()); ASSERT_TRUE(cr.all()); } TEST(ng_charreach, clear) { CharReach cr; ASSERT_EQ(0U, cr.count()); ASSERT_TRUE(cr.none()); ASSERT_FALSE(cr.all()); cr.set('q'); cr.set('u'); cr.set('a'); cr.set('r'); cr.set('k'); ASSERT_EQ(5U, cr.count()); cr.clear('r'); ASSERT_EQ(4U, cr.count()); ASSERT_FALSE(cr.test('r')); cr.setall(); ASSERT_EQ(cr.size(), cr.count()); ASSERT_TRUE(cr.all()); cr.clear(0xff); ASSERT_FALSE(cr.all()); } TEST(ng_charreach, copy) { CharReach cr; cr.set('a'); cr.set('z'); CharReach cr2(cr); ASSERT_EQ(cr.count(), cr2.count()); ASSERT_TRUE(cr == cr2); } TEST(ng_charreach, assignment) { CharReach cr; cr.set('f'); cr.set('l'); cr.set('y'); CharReach cr2; cr2 = cr; ASSERT_EQ(cr.count(), cr2.count()); ASSERT_TRUE(cr == cr2); } TEST(ng_charreach, flip) { CharReach cr; ASSERT_EQ(0U, cr.count()); ASSERT_TRUE(cr.none()); cr.flip(); ASSERT_EQ(cr.size(), cr.count()); ASSERT_TRUE(cr.all()); cr.flip(); ASSERT_EQ(0U, cr.count()); ASSERT_TRUE(cr.none()); cr.flip(25); ASSERT_FALSE(cr.none()); ASSERT_FALSE(cr.all()); ASSERT_EQ(1U, cr.count()); cr.flip(); ASSERT_EQ(cr.size() - 1, cr.count()); } TEST(ng_charreach, count) { CharReach cr; cr.set(1); cr.set(2); cr.set('a'); cr.set('Z'); cr.set('m'); cr.set('~'); cr.set(210); size_t n = cr.find_first(); ASSERT_FALSE(n == CharReach::npos); unsigned int i = 0; while (n != CharReach::npos) { i++; n = cr.find_next(n); } ASSERT_EQ(i, cr.count()); } TEST(ng_charreach, string) { CharReach cr; cr.set(1); cr.set(2); cr.set('a'); cr.set('Z'); cr.set('m'); cr.set('~'); cr.set(210); ASSERT_FALSE(cr.isAlpha()); cr.flip(1); cr.flip(2); cr.flip('~'); cr.flip(210); ASSERT_TRUE(cr.isAlpha()); ASSERT_EQ("Zam", cr.to_string()); } TEST(ng_charreach, alpha) { CharReach cr; ASSERT_EQ(0U, cr.count()); ASSERT_FALSE(cr.isAlpha()); cr.set('a'); ASSERT_FALSE(0 == cr.count()); ASSERT_TRUE(cr.isAlpha()); cr.set('A'); cr.set('b'); cr.set('z'); ASSERT_TRUE(cr.isAlpha()); cr.set(1); ASSERT_FALSE(cr.isAlpha()); } TEST(ng_charreach, alpha2) { // Test all single chars. for (size_t i = 0; i < 256; i++) { CharReach cr((unsigned char)i); ASSERT_EQ((i >= 'A' && i <= 'Z') || (i >= 'a' && i <= 'z'), cr.isAlpha()) << "Failed for char i=" << i; } // Test some more complex cases. ASSERT_FALSE(CharReach::dot().isAlpha()); ASSERT_FALSE(CharReach("0123456789").isAlpha()); ASSERT_FALSE(CharReach("a0").isAlpha()); ASSERT_FALSE(CharReach("abcdef0").isAlpha()); ASSERT_FALSE(CharReach('A', 'z').isAlpha()); ASSERT_FALSE(CharReach('A', 'Z' + 1).isAlpha()); ASSERT_FALSE(CharReach('A' - 1, 'Z').isAlpha()); ASSERT_FALSE(CharReach('a', 'z' + 1).isAlpha()); ASSERT_FALSE(CharReach('a' - 1, 'z').isAlpha()); ASSERT_TRUE(CharReach('A', 'B').isAlpha()); ASSERT_TRUE(CharReach('A', 'F').isAlpha()); ASSERT_TRUE(CharReach('A', 'Z').isAlpha()); ASSERT_TRUE(CharReach('X', 'Z').isAlpha()); ASSERT_TRUE(CharReach('a', 'b').isAlpha()); ASSERT_TRUE(CharReach('a', 'z').isAlpha()); ASSERT_TRUE(CharReach("ABCDEFabcdef").isAlpha()); } TEST(ng_charreach, caseless) { CharReach cr; cr.set('a'); ASSERT_FALSE(cr.isCaselessChar()); cr.set('A'); ASSERT_TRUE(cr.isCaselessChar()); cr.set('b'); ASSERT_FALSE(cr.isCaselessChar()); cr.set('B'); ASSERT_FALSE(cr.isCaselessChar()); } TEST(ng_charreach, caseless2) { // Test every pair of characters. for (size_t i = 0; i < 256; i++) { ASSERT_FALSE(CharReach((unsigned char)i).isCaselessChar()); for (size_t j = 0; j < 256; j++) { CharReach cr; cr.set(i); cr.set(j); bool upper_lower = (i >= 'A' && i <= 'Z') && j == i + 0x20; bool lower_upper = (i >= 'a' && i <= 'z') && i == j + 0x20; bool caseless_pair = upper_lower | lower_upper; ASSERT_EQ(caseless_pair, cr.isCaselessChar()) << "Failed for i=" << i << ", j=" << j; } } } TEST(ng_charreach, bitwise) { CharReach cr; CharReach cr2; CharReach cr3; CharReach cr4; cr.set('a'); cr2.set('z'); cr3.set('a'); cr3.set('z'); ASSERT_TRUE(cr < cr3); cr4 |= cr; cr4 |= cr2; ASSERT_TRUE(cr3 == cr4); ASSERT_TRUE(cr3 == (cr | cr2)); ASSERT_TRUE(cr4 == (cr | cr2)); ASSERT_TRUE(cr == (cr & cr3)); ASSERT_TRUE(cr2 == (cr2 & cr3)); cr3 &= cr; ASSERT_FALSE(cr3.test('z')); } TEST(ng_charreach, bit5) { CharReach cr; ASSERT_TRUE(cr.isBit5Insensitive()); cr.set('a'); ASSERT_FALSE(cr.isBit5Insensitive()); cr.set('A'); ASSERT_TRUE(cr.isBit5Insensitive()); cr.set('!'); ASSERT_FALSE(cr.isBit5Insensitive()); cr.set(1); ASSERT_TRUE(cr.isBit5Insensitive()); cr.clear(); cr.set('!'); cr.set('A'); ASSERT_FALSE(cr.isBit5Insensitive()); cr.clear(); cr.set('A'); cr.set('b'); ASSERT_FALSE(cr.isBit5Insensitive()); cr.set('a'); cr.set('B'); ASSERT_TRUE(cr.isBit5Insensitive()); } TEST(ng_charreach, find_last) { CharReach cr; cr.set('a'); ASSERT_EQ(cr.find_last(), (size_t)'a'); cr.set('b'); ASSERT_EQ(cr.find_last(), (size_t)'b'); cr.set(192); ASSERT_EQ(cr.find_last(), (size_t)192); cr.set(207); ASSERT_EQ(cr.find_last(), (size_t)207); cr.set(223); ASSERT_EQ(cr.find_last(), (size_t)223); cr.set(255); ASSERT_EQ(cr.find_last(), (size_t)255); cr.clear(); ASSERT_EQ(cr.find_last(), cr.size()); cr.set(0); ASSERT_EQ(cr.find_last(), (size_t)0); cr.set(1); ASSERT_EQ(cr.find_last(), (size_t)1); } TEST(ng_charreach, setRange) { // Exhaustive test: every possible contiguous range. for (unsigned range = 0; range < 256; range++) { for (unsigned from = 0; from < 256 - range; from++) { unsigned to = from + range; CharReach cr; cr.setRange(from, to); ASSERT_EQ(from, cr.find_first()); ASSERT_EQ(to, cr.find_last()); ASSERT_EQ(range + 1, cr.count()); } } } TEST(ng_charreach, find_nth) { const size_t npos = CharReach::npos; // One bit cases. for (size_t i = 0; i < 256; i++) { CharReach cr((unsigned char)i); ASSERT_EQ(i, cr.find_nth(0)); ASSERT_EQ(npos, cr.find_nth(1)); } // All bits set. CharReach dot = CharReach::dot(); for (size_t i = 0; i < 256; i++) { ASSERT_EQ(i, dot.find_nth(i)); } // Trivial two bit cases. for (size_t i = 0; i < 128; i++) { CharReach cr; cr.set(i); cr.set(256 - i); ASSERT_EQ(i, cr.find_nth(0)); ASSERT_EQ(256 - i, cr.find_nth(1)); ASSERT_EQ(npos, cr.find_nth(3)); } // More complex case. const std::string str("\x01\x02\x03\x05\x06\x20!#$%&./0123568:;ABCDEFMNOPUYZbcdefwxyz"); CharReach cr(str); for (size_t i = 0; i < str.length(); i++) { ASSERT_EQ(str[i], cr.find_nth(i)); } ASSERT_EQ(npos, cr.find_nth(str.length())); } TEST(ng_charreach, find_empty) { const size_t npos = CharReach::npos; ASSERT_EQ(npos, CharReach().find_first()); ASSERT_EQ(npos, CharReach().find_next(npos)); } TEST(ng_charreach, dot) { CharReach dot = CharReach::dot(); ASSERT_EQ(256, dot.count()); ASSERT_TRUE(dot.all()); for (size_t i = 0; i < 256; i++) { ASSERT_TRUE(dot.test(i)); } }