#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Automaton.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using namespace llvm;
using testing::ContainerEq;
using testing::UnorderedElementsAre;
#define GET_SymKind_DECL
#define GET_BinRequirementKindEnum_DECL
#include "AutomataTables.inc"
#define GET_SimpleAutomaton_DECL
#define GET_TupleAutomaton_DECL
#define GET_NfaAutomaton_DECL
#define GET_BinPackerAutomaton_DECL
#include "AutomataAutomata.inc"
TEST(Automata, SimpleAutomatonAcceptsFromInitialState) {
Automaton<SymKind> A(makeArrayRef(SimpleAutomatonTransitions));
EXPECT_TRUE(A.add(SK_a));
A.reset();
EXPECT_TRUE(A.add(SK_b));
A.reset();
EXPECT_TRUE(A.add(SK_c));
A.reset();
EXPECT_FALSE(A.add(SK_d));
}
TEST(Automata, SimpleAutomatonAcceptsSequences) {
Automaton<SymKind> A(makeArrayRef(SimpleAutomatonTransitions));
A.reset();
EXPECT_TRUE(A.add(SK_a));
EXPECT_TRUE(A.add(SK_b));
A.reset();
EXPECT_TRUE(A.add(SK_a));
EXPECT_FALSE(A.add(SK_c));
A.reset();
EXPECT_TRUE(A.add(SK_c));
EXPECT_FALSE(A.add(SK_a));
}
TEST(Automata, TupleAutomatonAccepts) {
Automaton<TupleAutomatonAction> A(makeArrayRef(TupleAutomatonTransitions));
A.reset();
EXPECT_TRUE(
A.add(TupleAutomatonAction{SK_a, SK_b, "yeet"}));
A.reset();
EXPECT_FALSE(
A.add(TupleAutomatonAction{SK_a, SK_a, "yeet"}));
A.reset();
EXPECT_FALSE(
A.add(TupleAutomatonAction{SK_a, SK_b, "feet"}));
A.reset();
EXPECT_TRUE(
A.add(TupleAutomatonAction{SK_b, SK_b, "foo"}));
}
TEST(Automata, NfaAutomatonAccepts) {
Automaton<SymKind> A(makeArrayRef(NfaAutomatonTransitions));
A.reset();
EXPECT_TRUE(A.add(SK_a));
EXPECT_TRUE(A.add(SK_a));
A.reset();
EXPECT_TRUE(A.add(SK_a));
EXPECT_TRUE(A.add(SK_b));
A.reset();
EXPECT_TRUE(A.add(SK_b));
EXPECT_TRUE(A.add(SK_a));
A.reset();
EXPECT_TRUE(A.add(SK_b));
EXPECT_TRUE(A.add(SK_b));
A.reset();
EXPECT_TRUE(A.add(SK_b));
EXPECT_TRUE(A.add(SK_b));
EXPECT_FALSE(A.add(SK_b));
}
TEST(Automata, BinPackerAutomatonAccepts) {
Automaton<BinPackerAutomatonAction> A(makeArrayRef(BinPackerAutomatonTransitions));
A.reset();
EXPECT_TRUE(A.add(BRK_0_to_4_dbl));
EXPECT_TRUE(A.add(BRK_0_to_4_dbl));
EXPECT_FALSE(A.add(BRK_0_to_4));
A.reset();
EXPECT_TRUE(A.add(BRK_0_to_4_dbl));
EXPECT_TRUE(A.add(BRK_0_to_4_dbl));
EXPECT_TRUE(A.add(BRK_0_to_6));
EXPECT_TRUE(A.add(BRK_0_to_6));
EXPECT_FALSE(A.add(BRK_0_to_6));
A.reset();
for (unsigned I = 0; I < 5; ++I)
EXPECT_TRUE(A.add(BRK_0_to_6));
EXPECT_FALSE(A.add(BRK_0_to_6_dbl));
}
#define BINS(a, b, c, d, e, f) \
((a << 5) | (b << 4) | (c << 3) | (d << 2) | (e << 1) | (f << 0))
TEST(Automata, BinPackerAutomatonExplains) {
Automaton<BinPackerAutomatonAction> A(makeArrayRef(BinPackerAutomatonTransitions),
makeArrayRef(BinPackerAutomatonTransitionInfo));
EXPECT_TRUE(A.add(BRK_0_to_4_dbl));
EXPECT_TRUE(A.add(BRK_0_to_4_dbl));
EXPECT_TRUE(A.add(BRK_0_to_6));
EXPECT_THAT(
A.getNfaPaths(),
UnorderedElementsAre(
ContainerEq(NfaPath{BINS(0, 0, 0, 0, 1, 1), BINS(0, 0, 1, 1, 1, 1),
BINS(1, 0, 1, 1, 1, 1)}),
ContainerEq(NfaPath{BINS(0, 0, 0, 0, 1, 1), BINS(0, 0, 1, 1, 1, 1),
BINS(0, 1, 1, 1, 1, 1)}),
ContainerEq(NfaPath{BINS(0, 0, 1, 1, 0, 0), BINS(0, 0, 1, 1, 1, 1),
BINS(1, 0, 1, 1, 1, 1)}),
ContainerEq(NfaPath{BINS(0, 0, 1, 1, 0, 0), BINS(0, 0, 1, 1, 1, 1),
BINS(0, 1, 1, 1, 1, 1)})));
}