blob: 99e6dc12e150829f62bb2923bc7d15e04b3ce84d [file] [log] [blame]
/*
* Copyright (C) 2016-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "Test.h"
#include <wtf/HashSet.h>
#include <wtf/OptionSet.h>
#include <wtf/OptionSetHash.h>
namespace TestWebKitAPI {
enum class ExampleFlags : uint64_t {
A = 1 << 0,
B = 1 << 1,
C = 1 << 2,
D = 1ULL << 31,
E = 1ULL << 63,
};
TEST(WTF_OptionSet, EmptySet)
{
OptionSet<ExampleFlags> set;
EXPECT_TRUE(set.isEmpty());
EXPECT_FALSE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
EXPECT_FALSE(set.contains(ExampleFlags::D));
EXPECT_FALSE(set.contains(ExampleFlags::E));
}
TEST(WTF_OptionSet, ContainsOneFlag)
{
OptionSet<ExampleFlags> set = ExampleFlags::A;
EXPECT_FALSE(set.isEmpty());
EXPECT_TRUE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
EXPECT_FALSE(set.contains(ExampleFlags::D));
EXPECT_FALSE(set.contains(ExampleFlags::E));
}
TEST(WTF_OptionSet, Equal)
{
OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::B };
EXPECT_TRUE((set == OptionSet<ExampleFlags> { ExampleFlags::A, ExampleFlags::B }));
EXPECT_TRUE((set == OptionSet<ExampleFlags> { ExampleFlags::B, ExampleFlags::A }));
EXPECT_FALSE(set == ExampleFlags::B);
}
TEST(WTF_OptionSet, NotEqual)
{
OptionSet<ExampleFlags> set = ExampleFlags::A;
EXPECT_TRUE(set != ExampleFlags::B);
EXPECT_FALSE(set != ExampleFlags::A);
}
TEST(WTF_OptionSet, Or)
{
OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::B, ExampleFlags::C };
OptionSet<ExampleFlags> set2 { ExampleFlags::C, ExampleFlags::D };
EXPECT_TRUE(((set | ExampleFlags::A) == OptionSet<ExampleFlags> { ExampleFlags::A, ExampleFlags::B, ExampleFlags::C }));
EXPECT_TRUE(((set | ExampleFlags::D) == OptionSet<ExampleFlags> { ExampleFlags::A, ExampleFlags::B, ExampleFlags::C, ExampleFlags::D }));
EXPECT_TRUE(((set | set2) == OptionSet<ExampleFlags> { ExampleFlags::A, ExampleFlags::B, ExampleFlags::C, ExampleFlags::D }));
}
TEST(WTF_OptionSet, Minus)
{
OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::B, ExampleFlags::C };
EXPECT_TRUE(((set - ExampleFlags::A) == OptionSet<ExampleFlags> { ExampleFlags::B, ExampleFlags::C }));
EXPECT_TRUE(((set - ExampleFlags::D) == OptionSet<ExampleFlags> { ExampleFlags::A, ExampleFlags::B, ExampleFlags::C }));
EXPECT_TRUE((set - set).isEmpty());
}
TEST(WTF_OptionSet, AddAndRemove)
{
OptionSet<ExampleFlags> set;
set.add(ExampleFlags::A);
EXPECT_TRUE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
set.add({ ExampleFlags::B, ExampleFlags::C });
EXPECT_TRUE(set.contains(ExampleFlags::A));
EXPECT_TRUE(set.contains(ExampleFlags::B));
EXPECT_TRUE(set.contains(ExampleFlags::C));
set.remove(ExampleFlags::B);
EXPECT_TRUE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_TRUE(set.contains(ExampleFlags::C));
set.remove({ ExampleFlags::A, ExampleFlags::C });
EXPECT_FALSE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
}
TEST(WTF_OptionSet, Set)
{
OptionSet<ExampleFlags> set;
set.set(ExampleFlags::A, true);
EXPECT_TRUE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
set.set({ ExampleFlags::B, ExampleFlags::C }, true);
EXPECT_TRUE(set.contains(ExampleFlags::A));
EXPECT_TRUE(set.contains(ExampleFlags::B));
EXPECT_TRUE(set.contains(ExampleFlags::C));
set.set(ExampleFlags::B, false);
EXPECT_TRUE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_TRUE(set.contains(ExampleFlags::C));
set.set({ ExampleFlags::A, ExampleFlags::C }, false);
EXPECT_FALSE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
}
TEST(WTF_OptionSet, ContainsTwoFlags)
{
OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::B };
EXPECT_FALSE(set.isEmpty());
EXPECT_TRUE(set.contains(ExampleFlags::A));
EXPECT_TRUE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
EXPECT_FALSE(set.contains(ExampleFlags::D));
EXPECT_FALSE(set.contains(ExampleFlags::E));
}
TEST(WTF_OptionSet, ContainsTwoFlags2)
{
OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::D };
EXPECT_FALSE(set.isEmpty());
EXPECT_TRUE(set.contains(ExampleFlags::A));
EXPECT_TRUE(set.contains(ExampleFlags::D));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
EXPECT_FALSE(set.contains(ExampleFlags::E));
}
TEST(WTF_OptionSet, ContainsTwoFlags3)
{
OptionSet<ExampleFlags> set { ExampleFlags::D, ExampleFlags::E };
EXPECT_FALSE(set.isEmpty());
EXPECT_TRUE(set.contains(ExampleFlags::D));
EXPECT_TRUE(set.contains(ExampleFlags::E));
EXPECT_FALSE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
}
TEST(WTF_OptionSet, EmptyOptionSetToRawValueToOptionSet)
{
OptionSet<ExampleFlags> set;
EXPECT_TRUE(set.isEmpty());
EXPECT_FALSE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
auto set2 = OptionSet<ExampleFlags>::fromRaw(set.toRaw());
EXPECT_TRUE(set2.isEmpty());
EXPECT_FALSE(set2.contains(ExampleFlags::A));
EXPECT_FALSE(set2.contains(ExampleFlags::B));
EXPECT_FALSE(set2.contains(ExampleFlags::C));
}
TEST(WTF_OptionSet, OptionSetThatContainsOneFlagToRawValueToOptionSet)
{
OptionSet<ExampleFlags> set = ExampleFlags::A;
EXPECT_FALSE(set.isEmpty());
EXPECT_TRUE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
EXPECT_FALSE(set.contains(ExampleFlags::D));
EXPECT_FALSE(set.contains(ExampleFlags::E));
auto set2 = OptionSet<ExampleFlags>::fromRaw(set.toRaw());
EXPECT_FALSE(set2.isEmpty());
EXPECT_TRUE(set2.contains(ExampleFlags::A));
EXPECT_FALSE(set2.contains(ExampleFlags::B));
EXPECT_FALSE(set2.contains(ExampleFlags::C));
EXPECT_FALSE(set2.contains(ExampleFlags::D));
EXPECT_FALSE(set2.contains(ExampleFlags::E));
}
TEST(WTF_OptionSet, OptionSetThatContainsOneFlagToRawValueToOptionSet2)
{
OptionSet<ExampleFlags> set = ExampleFlags::E;
EXPECT_FALSE(set.isEmpty());
EXPECT_TRUE(set.contains(ExampleFlags::E));
EXPECT_FALSE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
EXPECT_FALSE(set.contains(ExampleFlags::D));
auto set2 = OptionSet<ExampleFlags>::fromRaw(set.toRaw());
EXPECT_FALSE(set2.isEmpty());
EXPECT_TRUE(set2.contains(ExampleFlags::E));
EXPECT_FALSE(set2.contains(ExampleFlags::A));
EXPECT_FALSE(set2.contains(ExampleFlags::B));
EXPECT_FALSE(set2.contains(ExampleFlags::C));
EXPECT_FALSE(set2.contains(ExampleFlags::D));
}
TEST(WTF_OptionSet, OptionSetThatContainsTwoFlagsToRawValueToOptionSet)
{
OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::C };
EXPECT_FALSE(set.isEmpty());
EXPECT_TRUE(set.contains(ExampleFlags::A));
EXPECT_TRUE(set.contains(ExampleFlags::C));
EXPECT_FALSE(set.contains(ExampleFlags::B));
auto set2 = OptionSet<ExampleFlags>::fromRaw(set.toRaw());
EXPECT_FALSE(set2.isEmpty());
EXPECT_TRUE(set2.contains(ExampleFlags::A));
EXPECT_TRUE(set2.contains(ExampleFlags::C));
EXPECT_FALSE(set2.contains(ExampleFlags::B));
}
TEST(WTF_OptionSet, OptionSetThatContainsTwoFlagsToRawValueToOptionSet2)
{
OptionSet<ExampleFlags> set { ExampleFlags::D, ExampleFlags::E };
EXPECT_FALSE(set.isEmpty());
EXPECT_TRUE(set.contains(ExampleFlags::D));
EXPECT_TRUE(set.contains(ExampleFlags::E));
EXPECT_FALSE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
auto set2 = OptionSet<ExampleFlags>::fromRaw(set.toRaw());
EXPECT_FALSE(set2.isEmpty());
EXPECT_TRUE(set2.contains(ExampleFlags::D));
EXPECT_TRUE(set2.contains(ExampleFlags::E));
EXPECT_FALSE(set2.contains(ExampleFlags::A));
EXPECT_FALSE(set2.contains(ExampleFlags::B));
EXPECT_FALSE(set2.contains(ExampleFlags::C));
}
TEST(WTF_OptionSet, TwoIteratorsIntoSameOptionSet)
{
OptionSet<ExampleFlags> set { ExampleFlags::C, ExampleFlags::B };
OptionSet<ExampleFlags>::iterator it1 = set.begin();
OptionSet<ExampleFlags>::iterator it2 = it1;
++it1;
EXPECT_STRONG_ENUM_EQ(ExampleFlags::C, *it1);
EXPECT_STRONG_ENUM_EQ(ExampleFlags::B, *it2);
}
TEST(WTF_OptionSet, IterateOverOptionSetThatContainsTwoFlags)
{
OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::C };
OptionSet<ExampleFlags>::iterator it = set.begin();
OptionSet<ExampleFlags>::iterator end = set.end();
EXPECT_TRUE(it != end);
EXPECT_STRONG_ENUM_EQ(ExampleFlags::A, *it);
++it;
EXPECT_STRONG_ENUM_EQ(ExampleFlags::C, *it);
++it;
EXPECT_TRUE(it == end);
}
TEST(WTF_OptionSet, IterateOverOptionSetThatContainsFlags2)
{
OptionSet<ExampleFlags> set { ExampleFlags::D, ExampleFlags::E };
OptionSet<ExampleFlags>::iterator it = set.begin();
OptionSet<ExampleFlags>::iterator end = set.end();
EXPECT_TRUE(it != end);
EXPECT_STRONG_ENUM_EQ(ExampleFlags::D, *it);
++it;
EXPECT_STRONG_ENUM_EQ(ExampleFlags::E, *it);
++it;
EXPECT_TRUE(it == end);
}
TEST(WTF_OptionSet, NextItemAfterLargestIn32BitFlagSet)
{
enum class ThirtyTwoBitFlags : uint32_t {
A = 1UL << 31,
};
OptionSet<ThirtyTwoBitFlags> set { ThirtyTwoBitFlags::A };
OptionSet<ThirtyTwoBitFlags>::iterator it = set.begin();
OptionSet<ThirtyTwoBitFlags>::iterator end = set.end();
EXPECT_TRUE(it != end);
++it;
EXPECT_TRUE(it == end);
}
TEST(WTF_OptionSet, NextItemAfterLargestIn64BitFlagSet)
{
enum class SixtyFourBitFlags : uint64_t {
A = 1ULL << 63,
};
OptionSet<SixtyFourBitFlags> set { SixtyFourBitFlags::A };
OptionSet<SixtyFourBitFlags>::iterator it = set.begin();
OptionSet<SixtyFourBitFlags>::iterator end = set.end();
EXPECT_TRUE(it != end);
++it;
EXPECT_TRUE(it == end);
}
TEST(WTF_OptionSet, IterationOrderTheSameRegardlessOfInsertionOrder)
{
OptionSet<ExampleFlags> set1 = ExampleFlags::C;
set1.add(ExampleFlags::A);
OptionSet<ExampleFlags> set2 = ExampleFlags::A;
set2.add(ExampleFlags::C);
OptionSet<ExampleFlags>::iterator it1 = set1.begin();
OptionSet<ExampleFlags>::iterator it2 = set2.begin();
EXPECT_TRUE(*it1 == *it2);
++it1;
++it2;
EXPECT_TRUE(*it1 == *it2);
}
TEST(WTF_OptionSet, OperatorAnd)
{
OptionSet<ExampleFlags> a { ExampleFlags::A };
OptionSet<ExampleFlags> ac { ExampleFlags::A, ExampleFlags::C };
OptionSet<ExampleFlags> bc { ExampleFlags::B, ExampleFlags::C };
{
auto set = a & ac;
EXPECT_TRUE(!!set);
EXPECT_FALSE(set.isEmpty());
EXPECT_TRUE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
}
{
auto set = a & bc;
EXPECT_FALSE(!!set);
EXPECT_TRUE(set.isEmpty());
EXPECT_FALSE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
}
{
auto set = ac & bc;
EXPECT_TRUE(!!set);
EXPECT_FALSE(set.isEmpty());
EXPECT_FALSE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_TRUE(set.contains(ExampleFlags::C));
}
{
auto set = ExampleFlags::A & bc;
EXPECT_FALSE(!!set);
EXPECT_TRUE(set.isEmpty());
EXPECT_FALSE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
}
{
auto set = ExampleFlags::A & ac;
EXPECT_TRUE(!!set);
EXPECT_FALSE(set.isEmpty());
EXPECT_TRUE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
}
{
auto set = bc & ExampleFlags::A;
EXPECT_FALSE(!!set);
EXPECT_TRUE(set.isEmpty());
EXPECT_FALSE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
}
{
auto set = ac & ExampleFlags::A;
EXPECT_TRUE(!!set);
EXPECT_FALSE(set.isEmpty());
EXPECT_TRUE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
}
}
TEST(WTF_OptionSet, OperatorXor)
{
OptionSet<ExampleFlags> a { ExampleFlags::A };
OptionSet<ExampleFlags> ac { ExampleFlags::A, ExampleFlags::C };
OptionSet<ExampleFlags> bc { ExampleFlags::B, ExampleFlags::C };
{
auto set = a ^ ac;
EXPECT_FALSE(set.contains(ExampleFlags::A));
EXPECT_FALSE(set.contains(ExampleFlags::B));
EXPECT_TRUE(set.contains(ExampleFlags::C));
}
{
auto set = a ^ bc;
EXPECT_TRUE(set.contains(ExampleFlags::A));
EXPECT_TRUE(set.contains(ExampleFlags::B));
EXPECT_TRUE(set.contains(ExampleFlags::C));
}
{
auto set = ac ^ bc;
EXPECT_TRUE(set.contains(ExampleFlags::A));
EXPECT_TRUE(set.contains(ExampleFlags::B));
EXPECT_FALSE(set.contains(ExampleFlags::C));
}
}
TEST(WTF_OptionSet, ContainsAny)
{
OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::B };
EXPECT_TRUE(set.containsAny({ ExampleFlags::A }));
EXPECT_TRUE(set.containsAny({ ExampleFlags::B }));
EXPECT_FALSE(set.containsAny({ ExampleFlags::C }));
EXPECT_FALSE(set.containsAny({ ExampleFlags::C, ExampleFlags::D }));
EXPECT_TRUE(set.containsAny({ ExampleFlags::A, ExampleFlags::B }));
EXPECT_TRUE(set.containsAny({ ExampleFlags::B, ExampleFlags::C }));
EXPECT_TRUE(set.containsAny({ ExampleFlags::A, ExampleFlags::C }));
EXPECT_TRUE(set.containsAny({ ExampleFlags::A, ExampleFlags::B, ExampleFlags::C }));
}
TEST(WTF_OptionSet, ContainsAll)
{
OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::B };
EXPECT_TRUE(set.containsAll({ ExampleFlags::A }));
EXPECT_TRUE(set.containsAll({ ExampleFlags::B }));
EXPECT_FALSE(set.containsAll({ ExampleFlags::C }));
EXPECT_FALSE(set.containsAll({ ExampleFlags::C, ExampleFlags::D }));
EXPECT_TRUE(set.containsAll({ ExampleFlags::A, ExampleFlags::B }));
EXPECT_FALSE(set.containsAll({ ExampleFlags::B, ExampleFlags::C }));
EXPECT_FALSE(set.containsAll({ ExampleFlags::A, ExampleFlags::C }));
EXPECT_FALSE(set.containsAll({ ExampleFlags::A, ExampleFlags::B, ExampleFlags::C }));
}
TEST(WTF_OptionSet, HashSet)
{
HashSet<OptionSet<ExampleFlags>> hashSet;
EXPECT_TRUE(hashSet.add(OptionSet<ExampleFlags>()).isNewEntry);
EXPECT_TRUE(hashSet.add({ ExampleFlags::A }).isNewEntry);
EXPECT_TRUE(hashSet.add({ ExampleFlags::A, ExampleFlags::B }).isNewEntry);
EXPECT_FALSE(hashSet.add(OptionSet<ExampleFlags>()).isNewEntry);
EXPECT_FALSE(hashSet.add({ ExampleFlags::A }).isNewEntry);
EXPECT_FALSE(hashSet.add({ ExampleFlags::A, ExampleFlags::B }).isNewEntry);
EXPECT_TRUE(hashSet.remove(OptionSet<ExampleFlags>()));
EXPECT_TRUE(hashSet.remove({ ExampleFlags::A }));
EXPECT_TRUE(hashSet.remove({ ExampleFlags::A, ExampleFlags::B }));
EXPECT_TRUE(hashSet.add(OptionSet<ExampleFlags>()).isNewEntry);
EXPECT_TRUE(hashSet.add({ ExampleFlags::A }).isNewEntry);
EXPECT_TRUE(hashSet.add({ ExampleFlags::A, ExampleFlags::B }).isNewEntry);
}
} // namespace TestWebKitAPI