blob: 5c7834dd2e08ce3138aec9f665b31ced55125dec [file] [log] [blame] [edit]
/*
* Copyright 2023 WebAssembly Community Group participants
*
* Licensed 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 "analysis/lattices/array.h"
#include "analysis/lattices/bool.h"
#include "analysis/lattices/flat.h"
#include "analysis/lattices/int.h"
#include "analysis/lattices/inverted.h"
#include "analysis/lattices/lift.h"
#include "analysis/lattices/tuple.h"
#include "analysis/lattices/powerset2.h"
#include "analysis/lattices/vector.h"
#include "support/bitset.h"
#include "gtest/gtest.h"
using namespace wasm;
TEST(BoolLattice, GetBottom) {
analysis::Bool lattice;
EXPECT_FALSE(lattice.getBottom());
}
TEST(BoolLattice, GetTop) {
analysis::Bool lattice;
EXPECT_TRUE(lattice.getTop());
}
TEST(BoolLattice, Compare) {
analysis::Bool lattice;
EXPECT_EQ(lattice.compare(false, false), analysis::EQUAL);
EXPECT_EQ(lattice.compare(false, true), analysis::LESS);
EXPECT_EQ(lattice.compare(true, false), analysis::GREATER);
EXPECT_EQ(lattice.compare(true, true), analysis::EQUAL);
}
TEST(BoolLattice, Join) {
analysis::Bool lattice;
bool elem = false;
EXPECT_FALSE(lattice.join(elem, false));
ASSERT_FALSE(elem);
EXPECT_TRUE(lattice.join(elem, true));
ASSERT_TRUE(elem);
EXPECT_FALSE(lattice.join(elem, false));
ASSERT_TRUE(elem);
EXPECT_FALSE(lattice.join(elem, true));
ASSERT_TRUE(elem);
}
TEST(BoolLattice, Meet) {
analysis::Bool lattice;
bool elem = true;
EXPECT_FALSE(lattice.meet(elem, true));
ASSERT_TRUE(elem);
EXPECT_TRUE(lattice.meet(elem, false));
ASSERT_FALSE(elem);
EXPECT_FALSE(lattice.meet(elem, true));
ASSERT_FALSE(elem);
EXPECT_FALSE(lattice.meet(elem, false));
ASSERT_FALSE(elem);
}
TEST(IntLattice, GetBottom) {
analysis::Int32 int32;
EXPECT_EQ(int32.getBottom(), (int32_t)(1ull << 31));
analysis::Int64 int64;
EXPECT_EQ(int64.getBottom(), (int64_t)(1ull << 63));
analysis::UInt32 uint32;
EXPECT_EQ(uint32.getBottom(), (uint32_t)0);
analysis::UInt64 uint64;
EXPECT_EQ(uint64.getBottom(), (uint64_t)0);
}
TEST(IntLattice, GetTop) {
analysis::Int32 int32;
EXPECT_EQ(int32.getTop(), (int32_t)((1ull << 31) - 1));
analysis::Int64 int64;
EXPECT_EQ(int64.getTop(), (int64_t)((1ull << 63) - 1));
analysis::UInt32 uint32;
EXPECT_EQ(uint32.getTop(), (uint32_t)-1ull);
analysis::UInt64 uint64;
EXPECT_EQ(uint64.getTop(), (uint64_t)-1ull);
}
TEST(IntLattice, Compare) {
analysis::Int32 int32;
EXPECT_EQ(int32.compare(-5, 42), analysis::LESS);
EXPECT_EQ(int32.compare(42, -5), analysis::GREATER);
EXPECT_EQ(int32.compare(42, 42), analysis::EQUAL);
}
TEST(IntLattice, Join) {
analysis::Int32 int32;
int elem = 0;
EXPECT_FALSE(int32.join(elem, -10));
ASSERT_EQ(elem, 0);
EXPECT_FALSE(int32.join(elem, 0));
ASSERT_EQ(elem, 0);
EXPECT_TRUE(int32.join(elem, 100));
ASSERT_EQ(elem, 100);
}
TEST(IntLattice, Meet) {
analysis::Int32 int32;
int elem = 0;
EXPECT_FALSE(int32.meet(elem, 10));
ASSERT_EQ(elem, 0);
EXPECT_FALSE(int32.meet(elem, 0));
ASSERT_EQ(elem, 0);
EXPECT_TRUE(int32.meet(elem, -100));
ASSERT_EQ(elem, -100);
}
TEST(InvertedLattice, GetBottom) {
analysis::Inverted inverted(analysis::Bool{});
EXPECT_TRUE(inverted.getBottom());
}
TEST(InvertedLattice, GetTop) {
analysis::Inverted inverted(analysis::Bool{});
EXPECT_FALSE(inverted.getTop());
}
TEST(InvertedLattice, Compare) {
analysis::Inverted inverted(analysis::Bool{});
EXPECT_EQ(inverted.compare(false, false), analysis::EQUAL);
EXPECT_EQ(inverted.compare(false, true), analysis::GREATER);
EXPECT_EQ(inverted.compare(true, false), analysis::LESS);
EXPECT_EQ(inverted.compare(true, true), analysis::EQUAL);
}
TEST(InvertedLattice, Join) {
analysis::Inverted inverted(analysis::Bool{});
bool elem = true;
EXPECT_FALSE(inverted.join(elem, true));
ASSERT_TRUE(elem);
EXPECT_TRUE(inverted.join(elem, false));
ASSERT_FALSE(elem);
EXPECT_FALSE(inverted.join(elem, true));
ASSERT_FALSE(elem);
EXPECT_FALSE(inverted.join(elem, false));
ASSERT_FALSE(elem);
}
TEST(InvertedLattice, Meet) {
analysis::Inverted inverted(analysis::Bool{});
bool elem = false;
EXPECT_FALSE(inverted.meet(elem, false));
ASSERT_FALSE(elem);
EXPECT_TRUE(inverted.meet(elem, true));
ASSERT_TRUE(elem);
EXPECT_FALSE(inverted.meet(elem, false));
ASSERT_TRUE(elem);
EXPECT_FALSE(inverted.meet(elem, true));
ASSERT_TRUE(elem);
}
TEST(InvertedLattice, DoubleInverted) {
using DoubleInverted = analysis::Inverted<analysis::Inverted<analysis::Bool>>;
DoubleInverted identity(analysis::Inverted<analysis::Bool>{analysis::Bool{}});
EXPECT_FALSE(identity.getBottom());
EXPECT_TRUE(identity.getTop());
}
TEST(FlatLattice, GetBottom) {
analysis::Flat<int> flat;
EXPECT_TRUE(flat.getBottom().isBottom());
EXPECT_FALSE(flat.getBottom().getVal());
EXPECT_FALSE(flat.getBottom().isTop());
}
TEST(FlatLattice, GetVal) {
analysis::Flat<int> flat;
EXPECT_FALSE(flat.get(10).isBottom());
ASSERT_TRUE(flat.get(10).getVal());
EXPECT_FALSE(flat.get(10).isTop());
auto val = flat.get(10);
EXPECT_EQ(*val.getVal(), 10);
}
TEST(FlatLattice, GetTop) {
analysis::Flat<int> flat;
EXPECT_FALSE(flat.getTop().isBottom());
EXPECT_FALSE(flat.getTop().getVal());
EXPECT_TRUE(flat.getTop().isTop());
}
TEST(FlatLattice, Compare) {
analysis::Flat<int> flat;
auto bot = flat.getBottom();
auto a = flat.get(0);
auto b = flat.get(1);
auto top = flat.getTop();
EXPECT_EQ(flat.compare(bot, bot), analysis::EQUAL);
EXPECT_EQ(flat.compare(bot, a), analysis::LESS);
EXPECT_EQ(flat.compare(bot, b), analysis::LESS);
EXPECT_EQ(flat.compare(bot, top), analysis::LESS);
EXPECT_EQ(flat.compare(a, bot), analysis::GREATER);
EXPECT_EQ(flat.compare(a, a), analysis::EQUAL);
EXPECT_EQ(flat.compare(a, b), analysis::NO_RELATION);
EXPECT_EQ(flat.compare(a, top), analysis::LESS);
EXPECT_EQ(flat.compare(b, bot), analysis::GREATER);
EXPECT_EQ(flat.compare(b, a), analysis::NO_RELATION);
EXPECT_EQ(flat.compare(b, b), analysis::EQUAL);
EXPECT_EQ(flat.compare(b, top), analysis::LESS);
EXPECT_EQ(flat.compare(top, bot), analysis::GREATER);
EXPECT_EQ(flat.compare(top, a), analysis::GREATER);
EXPECT_EQ(flat.compare(top, b), analysis::GREATER);
EXPECT_EQ(flat.compare(top, top), analysis::EQUAL);
}
TEST(FlatLattice, Join) {
analysis::Flat<int> flat;
auto elem = flat.getBottom();
// bot u bot = bot
EXPECT_FALSE(flat.join(elem, flat.getBottom()));
EXPECT_TRUE(elem.isBottom());
// bot u top = top
EXPECT_TRUE(flat.join(elem, flat.getTop()));
EXPECT_TRUE(elem.isTop());
// bot u 10 = 10
elem = flat.getBottom();
EXPECT_TRUE(flat.join(elem, flat.get(10)));
ASSERT_TRUE(elem.getVal());
EXPECT_EQ(*elem.getVal(), 10);
// 10 u bot = 10
EXPECT_FALSE(flat.join(elem, flat.getBottom()));
ASSERT_TRUE(elem.getVal());
EXPECT_EQ(*elem.getVal(), 10);
// 10 u 10 = 10
EXPECT_FALSE(flat.join(elem, flat.get(10)));
ASSERT_TRUE(elem.getVal());
EXPECT_EQ(*elem.getVal(), 10);
// 10 u 999 = top
EXPECT_TRUE(flat.join(elem, flat.get(999)));
ASSERT_TRUE(elem.isTop());
// 10 u top = top
elem = flat.get(10);
EXPECT_TRUE(flat.join(elem, flat.getTop()));
ASSERT_TRUE(elem.isTop());
// top u bot = top
EXPECT_FALSE(flat.join(elem, flat.getBottom()));
EXPECT_TRUE(elem.isTop());
// top u 10 = top
EXPECT_FALSE(flat.join(elem, flat.get(10)));
EXPECT_TRUE(elem.isTop());
// top u top = top
EXPECT_FALSE(flat.join(elem, flat.getTop()));
EXPECT_TRUE(elem.isTop());
}
TEST(LiftLattice, GetBottom) {
analysis::Lift lift{analysis::Bool{}};
EXPECT_TRUE(lift.getBottom().isBottom());
EXPECT_FALSE(lift.getBottom().has_value());
}
TEST(LiftLattice, GetVal) {
analysis::Lift lift{analysis::Bool{}};
EXPECT_FALSE(lift.get(false).isBottom());
EXPECT_FALSE(lift.get(true).isBottom());
EXPECT_FALSE(*lift.get(false));
EXPECT_TRUE(*lift.get(true));
analysis::Lift liftInt{analysis::Int32{}};
EXPECT_FALSE(liftInt.get(10).isBottom());
EXPECT_EQ(*liftInt.get(0), 0);
EXPECT_EQ(*liftInt.get(10), 10);
}
TEST(LiftLattice, Compare) {
analysis::Lift lift{analysis::Flat<bool>{}};
auto& liftee = lift.lattice;
auto bot = lift.getBottom();
auto lifteeBot = lift.get(liftee.getBottom());
auto a = lift.get(liftee.get(false));
auto b = lift.get(liftee.get(true));
auto top = lift.get(liftee.getTop());
EXPECT_EQ(lift.compare(bot, bot), analysis::EQUAL);
EXPECT_EQ(lift.compare(bot, lifteeBot), analysis::LESS);
EXPECT_EQ(lift.compare(bot, a), analysis::LESS);
EXPECT_EQ(lift.compare(bot, b), analysis::LESS);
EXPECT_EQ(lift.compare(bot, top), analysis::LESS);
EXPECT_EQ(lift.compare(lifteeBot, bot), analysis::GREATER);
EXPECT_EQ(lift.compare(a, bot), analysis::GREATER);
EXPECT_EQ(lift.compare(b, bot), analysis::GREATER);
EXPECT_EQ(lift.compare(top, bot), analysis::GREATER);
EXPECT_EQ(lift.compare(a, b), analysis::NO_RELATION);
EXPECT_EQ(lift.compare(a, top), analysis::LESS);
EXPECT_EQ(lift.compare(a, lifteeBot), analysis::GREATER);
}
TEST(LiftLattice, Join) {
analysis::Lift lift{analysis::Bool{}};
auto bot = lift.getBottom();
auto lifteeBot = lift.get(false);
auto top = lift.get(true);
// bot u bot = bot
auto elem = bot;
EXPECT_FALSE(lift.join(elem, bot));
EXPECT_EQ(elem, bot);
// bot u lifteeBot = lifteeBot
EXPECT_TRUE(lift.join(elem, lifteeBot));
EXPECT_EQ(elem, lifteeBot);
// lifteeBot u bot = lifteeBot
EXPECT_FALSE(lift.join(elem, bot));
EXPECT_EQ(elem, lifteeBot);
// lifteeBot u lifteeBot = lifteeBot
EXPECT_FALSE(lift.join(elem, lifteeBot));
EXPECT_EQ(elem, lifteeBot);
// lifteeBot u top = top
EXPECT_TRUE(lift.join(elem, top));
EXPECT_EQ(elem, top);
// top u bot = top
EXPECT_FALSE(lift.join(elem, bot));
EXPECT_EQ(elem, top);
}
TEST(ArrayLattice, GetBottom) {
analysis::Array<analysis::Bool, 2> array{analysis::Bool{}};
EXPECT_EQ(array.getBottom(), (std::array<bool, 2>{false, false}));
}
TEST(ArrayLattice, GetTop) {
analysis::Array<analysis::Bool, 2> array{analysis::Bool{}};
EXPECT_EQ(array.getTop(), (std::array<bool, 2>{true, true}));
}
TEST(ArrayLattice, Compare) {
analysis::Array<analysis::Bool, 2> array{analysis::Bool{}};
std::array<bool, 2> ff{false, false};
std::array<bool, 2> ft{false, true};
std::array<bool, 2> tf{true, false};
std::array<bool, 2> tt{true, true};
EXPECT_EQ(array.compare(ff, ff), analysis::EQUAL);
EXPECT_EQ(array.compare(ff, ft), analysis::LESS);
EXPECT_EQ(array.compare(ff, tf), analysis::LESS);
EXPECT_EQ(array.compare(ff, tt), analysis::LESS);
EXPECT_EQ(array.compare(ft, ff), analysis::GREATER);
EXPECT_EQ(array.compare(ft, ft), analysis::EQUAL);
EXPECT_EQ(array.compare(ft, tf), analysis::NO_RELATION);
EXPECT_EQ(array.compare(ft, tt), analysis::LESS);
EXPECT_EQ(array.compare(tf, ff), analysis::GREATER);
EXPECT_EQ(array.compare(tf, ft), analysis::NO_RELATION);
EXPECT_EQ(array.compare(tf, tf), analysis::EQUAL);
EXPECT_EQ(array.compare(tf, tt), analysis::LESS);
EXPECT_EQ(array.compare(tt, ff), analysis::GREATER);
EXPECT_EQ(array.compare(tt, ft), analysis::GREATER);
EXPECT_EQ(array.compare(tt, tf), analysis::GREATER);
EXPECT_EQ(array.compare(tt, tt), analysis::EQUAL);
}
TEST(ArrayLattice, Join) {
analysis::Array<analysis::Bool, 2> array{analysis::Bool{}};
auto ff = []() { return std::array<bool, 2>{false, false}; };
auto ft = []() { return std::array<bool, 2>{false, true}; };
auto tf = []() { return std::array<bool, 2>{true, false}; };
auto tt = []() { return std::array<bool, 2>{true, true}; };
auto test =
[&](auto& makeJoinee, auto& makeJoiner, bool modified, auto& makeExpected) {
auto joinee = makeJoinee();
EXPECT_EQ(array.join(joinee, makeJoiner()), modified);
EXPECT_EQ(joinee, makeExpected());
};
test(ff, ff, false, ff);
test(ff, ft, true, ft);
test(ff, tf, true, tf);
test(ff, tt, true, tt);
test(ft, ff, false, ft);
test(ft, ft, false, ft);
test(ft, tf, true, tt);
test(ft, tt, true, tt);
test(tf, ff, false, tf);
test(tf, ft, true, tt);
test(tf, tf, false, tf);
test(tf, tt, true, tt);
test(tt, ff, false, tt);
test(tt, ft, false, tt);
test(tt, tf, false, tt);
test(tt, tt, false, tt);
}
TEST(ArrayLattice, Meet) {
analysis::Array<analysis::Bool, 2> array{analysis::Bool{}};
auto ff = []() { return std::array<bool, 2>{false, false}; };
auto ft = []() { return std::array<bool, 2>{false, true}; };
auto tf = []() { return std::array<bool, 2>{true, false}; };
auto tt = []() { return std::array<bool, 2>{true, true}; };
auto test =
[&](auto& makeMeetee, auto& makeMeeter, bool modified, auto& makeExpected) {
auto meetee = makeMeetee();
EXPECT_EQ(array.meet(meetee, makeMeeter()), modified);
EXPECT_EQ(meetee, makeExpected());
};
test(ff, ff, false, ff);
test(ff, ft, false, ff);
test(ff, tf, false, ff);
test(ff, tt, false, ff);
test(ft, ff, true, ff);
test(ft, ft, false, ft);
test(ft, tf, true, ff);
test(ft, tt, false, ft);
test(tf, ff, true, ff);
test(tf, ft, true, ff);
test(tf, tf, false, tf);
test(tf, tt, false, tf);
test(tt, ff, true, ff);
test(tt, ft, true, ft);
test(tt, tf, true, tf);
test(tt, tt, false, tt);
}
TEST(VectorLattice, GetBottom) {
analysis::Vector<analysis::Bool> vector{analysis::Bool{}, 2};
EXPECT_EQ(vector.getBottom(), (std::vector<bool>{false, false}));
}
TEST(VectorLattice, GetTop) {
analysis::Vector<analysis::Bool> vector{analysis::Bool{}, 2};
EXPECT_EQ(vector.getTop(), (std::vector<bool>{true, true}));
}
TEST(VectorLattice, Compare) {
analysis::Vector<analysis::Bool> vector{analysis::Bool{}, 2};
std::vector<bool> ff{false, false};
std::vector<bool> ft{false, true};
std::vector<bool> tf{true, false};
std::vector<bool> tt{true, true};
EXPECT_EQ(vector.compare(ff, ff), analysis::EQUAL);
EXPECT_EQ(vector.compare(ff, ft), analysis::LESS);
EXPECT_EQ(vector.compare(ff, tf), analysis::LESS);
EXPECT_EQ(vector.compare(ff, tt), analysis::LESS);
EXPECT_EQ(vector.compare(ft, ff), analysis::GREATER);
EXPECT_EQ(vector.compare(ft, ft), analysis::EQUAL);
EXPECT_EQ(vector.compare(ft, tf), analysis::NO_RELATION);
EXPECT_EQ(vector.compare(ft, tt), analysis::LESS);
EXPECT_EQ(vector.compare(tf, ff), analysis::GREATER);
EXPECT_EQ(vector.compare(tf, ft), analysis::NO_RELATION);
EXPECT_EQ(vector.compare(tf, tf), analysis::EQUAL);
EXPECT_EQ(vector.compare(tf, tt), analysis::LESS);
EXPECT_EQ(vector.compare(tt, ff), analysis::GREATER);
EXPECT_EQ(vector.compare(tt, ft), analysis::GREATER);
EXPECT_EQ(vector.compare(tt, tf), analysis::GREATER);
EXPECT_EQ(vector.compare(tt, tt), analysis::EQUAL);
}
TEST(VectorLattice, Join) {
analysis::Vector<analysis::Bool> vector{analysis::Bool{}, 2};
auto ff = []() { return std::vector<bool>{false, false}; };
auto ft = []() { return std::vector<bool>{false, true}; };
auto tf = []() { return std::vector<bool>{true, false}; };
auto tt = []() { return std::vector<bool>{true, true}; };
auto test =
[&](auto& makeJoinee, auto& makeJoiner, bool modified, auto& makeExpected) {
auto joinee = makeJoinee();
EXPECT_EQ(vector.join(joinee, makeJoiner()), modified);
EXPECT_EQ(joinee, makeExpected());
};
test(ff, ff, false, ff);
test(ff, ft, true, ft);
test(ff, tf, true, tf);
test(ff, tt, true, tt);
test(ft, ff, false, ft);
test(ft, ft, false, ft);
test(ft, tf, true, tt);
test(ft, tt, true, tt);
test(tf, ff, false, tf);
test(tf, ft, true, tt);
test(tf, tf, false, tf);
test(tf, tt, true, tt);
test(tt, ff, false, tt);
test(tt, ft, false, tt);
test(tt, tf, false, tt);
test(tt, tt, false, tt);
}
TEST(VectorLattice, Meet) {
analysis::Vector<analysis::Bool> vector{analysis::Bool{}, 2};
auto ff = []() { return std::vector<bool>{false, false}; };
auto ft = []() { return std::vector<bool>{false, true}; };
auto tf = []() { return std::vector<bool>{true, false}; };
auto tt = []() { return std::vector<bool>{true, true}; };
auto test =
[&](auto& makeMeetee, auto& makeMeeter, bool modified, auto& makeExpected) {
auto meetee = makeMeetee();
EXPECT_EQ(vector.meet(meetee, makeMeeter()), modified);
EXPECT_EQ(meetee, makeExpected());
};
test(ff, ff, false, ff);
test(ff, ft, false, ff);
test(ff, tf, false, ff);
test(ff, tt, false, ff);
test(ft, ff, true, ff);
test(ft, ft, false, ft);
test(ft, tf, true, ff);
test(ft, tt, false, ft);
test(tf, ff, true, ff);
test(tf, ft, true, ff);
test(tf, tf, false, tf);
test(tf, tt, false, tf);
test(tt, ff, true, ff);
test(tt, ft, true, ft);
test(tt, tf, true, tf);
test(tt, tt, false, tt);
}
TEST(TupleLattice, GetBottom) {
analysis::Tuple<analysis::Bool, analysis::UInt32> tuple{analysis::Bool{},
analysis::UInt32{}};
EXPECT_EQ(tuple.getBottom(), (std::tuple{false, 0}));
}
TEST(TupleLattice, GetTop) {
analysis::Tuple<analysis::Bool, analysis::UInt32> tuple{analysis::Bool{},
analysis::UInt32{}};
EXPECT_EQ(tuple.getTop(), (std::tuple{true, uint32_t(-1)}));
}
TEST(TupleLattice, Compare) {
analysis::Tuple<analysis::Bool, analysis::UInt32> tuple{analysis::Bool{},
analysis::UInt32{}};
std::tuple<bool, uint32_t> ff{false, 0};
std::tuple<bool, uint32_t> ft{false, 1};
std::tuple<bool, uint32_t> tf{true, 0};
std::tuple<bool, uint32_t> tt{true, 1};
EXPECT_EQ(tuple.compare(ff, ff), analysis::EQUAL);
EXPECT_EQ(tuple.compare(ff, ft), analysis::LESS);
EXPECT_EQ(tuple.compare(ff, tf), analysis::LESS);
EXPECT_EQ(tuple.compare(ff, tt), analysis::LESS);
EXPECT_EQ(tuple.compare(ft, ff), analysis::GREATER);
EXPECT_EQ(tuple.compare(ft, ft), analysis::EQUAL);
EXPECT_EQ(tuple.compare(ft, tf), analysis::NO_RELATION);
EXPECT_EQ(tuple.compare(ft, tt), analysis::LESS);
EXPECT_EQ(tuple.compare(tf, ff), analysis::GREATER);
EXPECT_EQ(tuple.compare(tf, ft), analysis::NO_RELATION);
EXPECT_EQ(tuple.compare(tf, tf), analysis::EQUAL);
EXPECT_EQ(tuple.compare(tf, tt), analysis::LESS);
EXPECT_EQ(tuple.compare(tt, ff), analysis::GREATER);
EXPECT_EQ(tuple.compare(tt, ft), analysis::GREATER);
EXPECT_EQ(tuple.compare(tt, tf), analysis::GREATER);
EXPECT_EQ(tuple.compare(tt, tt), analysis::EQUAL);
}
TEST(TupleLattice, Join) {
analysis::Tuple<analysis::Bool, analysis::UInt32> tuple{analysis::Bool{},
analysis::UInt32{}};
auto ff = []() { return std::tuple<bool, uint32_t>{false, 0}; };
auto ft = []() { return std::tuple<bool, uint32_t>{false, 1}; };
auto tf = []() { return std::tuple<bool, uint32_t>{true, 0}; };
auto tt = []() { return std::tuple<bool, uint32_t>{true, 1}; };
auto test =
[&](auto& makeJoinee, auto& makeJoiner, bool modified, auto& makeExpected) {
auto joinee = makeJoinee();
EXPECT_EQ(tuple.join(joinee, makeJoiner()), modified);
EXPECT_EQ(joinee, makeExpected());
};
test(ff, ff, false, ff);
test(ff, ft, true, ft);
test(ff, tf, true, tf);
test(ff, tt, true, tt);
test(ft, ff, false, ft);
test(ft, ft, false, ft);
test(ft, tf, true, tt);
test(ft, tt, true, tt);
test(tf, ff, false, tf);
test(tf, ft, true, tt);
test(tf, tf, false, tf);
test(tf, tt, true, tt);
test(tt, ff, false, tt);
test(tt, ft, false, tt);
test(tt, tf, false, tt);
test(tt, tt, false, tt);
}
TEST(TupleLattice, Meet) {
analysis::Tuple<analysis::Bool, analysis::UInt32> tuple{analysis::Bool{},
analysis::UInt32{}};
auto ff = []() { return std::tuple<bool, uint32_t>{false, 0}; };
auto ft = []() { return std::tuple<bool, uint32_t>{false, 1}; };
auto tf = []() { return std::tuple<bool, uint32_t>{true, 0}; };
auto tt = []() { return std::tuple<bool, uint32_t>{true, 1}; };
auto test =
[&](auto& makeMeetee, auto& makeMeeter, bool modified, auto& makeExpected) {
auto meetee = makeMeetee();
EXPECT_EQ(tuple.meet(meetee, makeMeeter()), modified);
EXPECT_EQ(meetee, makeExpected());
};
test(ff, ff, false, ff);
test(ff, ft, false, ff);
test(ff, tf, false, ff);
test(ff, tt, false, ff);
test(ft, ff, true, ff);
test(ft, ft, false, ft);
test(ft, tf, true, ff);
test(ft, tt, false, ft);
test(tf, ff, true, ff);
test(tf, ft, true, ff);
test(tf, tf, false, tf);
test(tf, tt, false, tf);
test(tt, ff, true, ff);
test(tt, ft, true, ft);
test(tt, tf, true, tf);
test(tt, tt, false, tt);
}
template<typename Set> void testPowersetGetBottom() {
analysis::Powerset2<Set> powerset;
auto bot = powerset.getBottom();
EXPECT_EQ(bot, Set{});
EXPECT_TRUE(bot.empty());
}
template<typename Set> void testPowersetGetTop() {
analysis::FinitePowerset2<Set> powerset{0, 1};
auto top = powerset.getTop();
EXPECT_EQ(top, (Set{0, 1}));
}
template<typename Set> void testPowersetCompare() {
analysis::Powerset2<Set> powerset;
Set ff{};
Set ft{0};
Set tf{1};
Set tt{0, 1};
EXPECT_EQ(powerset.compare(ff, ff), analysis::EQUAL);
EXPECT_EQ(powerset.compare(ff, ft), analysis::LESS);
EXPECT_EQ(powerset.compare(ff, tf), analysis::LESS);
EXPECT_EQ(powerset.compare(ff, tt), analysis::LESS);
EXPECT_EQ(powerset.compare(ft, ff), analysis::GREATER);
EXPECT_EQ(powerset.compare(ft, ft), analysis::EQUAL);
EXPECT_EQ(powerset.compare(ft, tf), analysis::NO_RELATION);
EXPECT_EQ(powerset.compare(ft, tt), analysis::LESS);
EXPECT_EQ(powerset.compare(tf, ff), analysis::GREATER);
EXPECT_EQ(powerset.compare(tf, ft), analysis::NO_RELATION);
EXPECT_EQ(powerset.compare(tf, tf), analysis::EQUAL);
EXPECT_EQ(powerset.compare(tf, tt), analysis::LESS);
EXPECT_EQ(powerset.compare(tt, ff), analysis::GREATER);
EXPECT_EQ(powerset.compare(tt, ft), analysis::GREATER);
EXPECT_EQ(powerset.compare(tt, tf), analysis::GREATER);
EXPECT_EQ(powerset.compare(tt, tt), analysis::EQUAL);
}
template<typename Set> void testPowersetJoin() {
analysis::Powerset2<Set> powerset;
auto ff = []() { return Set{}; };
auto ft = []() { return Set{0}; };
auto tf = []() { return Set{1}; };
auto tt = []() { return Set{0, 1}; };
auto test =
[&](auto& makeJoinee, auto& makeJoiner, bool modified, auto& makeExpected) {
auto joinee = makeJoinee();
EXPECT_EQ(powerset.join(joinee, makeJoiner()), modified);
EXPECT_EQ(joinee, makeExpected());
};
test(ff, ff, false, ff);
test(ff, ft, true, ft);
test(ff, tf, true, tf);
test(ff, tt, true, tt);
test(ft, ff, false, ft);
test(ft, ft, false, ft);
test(ft, tf, true, tt);
test(ft, tt, true, tt);
test(tf, ff, false, tf);
test(tf, ft, true, tt);
test(tf, tf, false, tf);
test(tf, tt, true, tt);
test(tt, ff, false, tt);
test(tt, ft, false, tt);
test(tt, tf, false, tt);
test(tt, tt, false, tt);
}
template<typename Set> void testPowersetMeet() {
analysis::FinitePowerset2<Set> powerset{0, 1};
auto ff = []() { return Set{}; };
auto ft = []() { return Set{0}; };
auto tf = []() { return Set{1}; };
auto tt = []() { return Set{0, 1}; };
auto test =
[&](auto& makeMeetee, auto& makeMeeter, bool modified, auto& makeExpected) {
auto meetee = makeMeetee();
EXPECT_EQ(powerset.meet(meetee, makeMeeter()), modified);
EXPECT_EQ(meetee, makeExpected());
};
test(ff, ff, false, ff);
test(ff, ft, false, ff);
test(ff, tf, false, ff);
test(ff, tt, false, ff);
test(ft, ff, true, ff);
test(ft, ft, false, ft);
test(ft, tf, true, ff);
test(ft, tt, false, ft);
test(tf, ff, true, ff);
test(tf, ft, true, ff);
test(tf, tf, false, tf);
test(tf, tt, false, tf);
test(tt, ff, true, ff);
test(tt, ft, true, ft);
test(tt, tf, true, tf);
test(tt, tt, false, tt);
}
TEST(PowersetLattice, GetBottom) {
testPowersetGetBottom<std::unordered_set<int>>();
}
TEST(PowersetLattice, GetTop) { testPowersetGetTop<std::unordered_set<int>>(); }
TEST(PowersetLattice, Compare) {
testPowersetCompare<std::unordered_set<int>>();
}
TEST(PowersetLattice, Join) { testPowersetJoin<std::unordered_set<int>>(); }
TEST(PowersetLattice, Meet) { testPowersetMeet<std::unordered_set<int>>(); }
TEST(PowersetBitLattice, GetBottom) { testPowersetGetBottom<BitSet>(); }
TEST(PowersetBitLattice, GetTop) { testPowersetGetTop<BitSet>(); }
TEST(PowersetBitLattice, Compare) { testPowersetCompare<BitSet>(); }
TEST(PowersetBitLattice, Join) { testPowersetJoin<BitSet>(); }
TEST(PowersetBitLattice, Meet) { testPowersetMeet<BitSet>(); }