blob: 67ef370676f528ac0141b2f92798df5ec1198696 [file] [log] [blame]
//
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// IntermNode_test.cpp:
// Unit tests for the AST node classes.
//
#include "angle_gl.h"
#include "gtest/gtest.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/PoolAlloc.h"
using namespace sh;
class IntermNodeTest : public testing::Test
{
public:
IntermNodeTest() : mUniqueIndex(0) {}
protected:
void SetUp() override
{
allocator.push();
SetGlobalPoolAllocator(&allocator);
}
void TearDown() override
{
SetGlobalPoolAllocator(nullptr);
allocator.pop();
}
TIntermSymbol *createTestSymbol(const TType &type)
{
TInfoSinkBase symbolNameOut;
symbolNameOut << "test" << mUniqueIndex;
TString symbolName = symbolNameOut.c_str();
++mUniqueIndex;
TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
node->setLine(createUniqueSourceLoc());
node->setInternal(true);
node->getTypePointer()->setQualifier(EvqTemporary);
return node;
}
TIntermSymbol *createTestSymbol()
{
TType type(EbtFloat, EbpHigh);
return createTestSymbol(type);
}
void checkTypeEqualWithQualifiers(const TType &original, const TType &copy)
{
ASSERT_EQ(original, copy);
ASSERT_EQ(original.getPrecision(), copy.getPrecision());
ASSERT_EQ(original.getQualifier(), copy.getQualifier());
}
void checkSymbolCopy(TIntermNode *aOriginal, TIntermNode *aCopy)
{
ASSERT_NE(aOriginal, aCopy);
TIntermSymbol *copy = aCopy->getAsSymbolNode();
TIntermSymbol *original = aOriginal->getAsSymbolNode();
ASSERT_NE(nullptr, copy);
ASSERT_NE(nullptr, original);
ASSERT_NE(original, copy);
ASSERT_EQ(original->getId(), copy->getId());
ASSERT_EQ(original->getName().getString(), copy->getName().getString());
ASSERT_EQ(original->getName().isInternal(), copy->getName().isInternal());
checkTypeEqualWithQualifiers(original->getType(), copy->getType());
ASSERT_EQ(original->getLine().first_file, copy->getLine().first_file);
ASSERT_EQ(original->getLine().first_line, copy->getLine().first_line);
ASSERT_EQ(original->getLine().last_file, copy->getLine().last_file);
ASSERT_EQ(original->getLine().last_line, copy->getLine().last_line);
}
TSourceLoc createUniqueSourceLoc()
{
TSourceLoc loc;
loc.first_file = mUniqueIndex;
loc.first_line = mUniqueIndex + 1;
loc.last_file = mUniqueIndex + 2;
loc.last_line = mUniqueIndex + 3;
++mUniqueIndex;
return loc;
}
static TSourceLoc getTestSourceLoc()
{
TSourceLoc loc;
loc.first_file = 1;
loc.first_line = 2;
loc.last_file = 3;
loc.last_line = 4;
return loc;
}
static void checkTestSourceLoc(const TSourceLoc &loc)
{
ASSERT_EQ(1, loc.first_file);
ASSERT_EQ(2, loc.first_line);
ASSERT_EQ(3, loc.last_file);
ASSERT_EQ(4, loc.last_line);
}
private:
TPoolAllocator allocator;
int mUniqueIndex;
};
// Check that the deep copy of a symbol node is an actual copy with the same attributes as the
// original.
TEST_F(IntermNodeTest, DeepCopySymbolNode)
{
TType type(EbtInt, EbpHigh);
TIntermSymbol *original = new TIntermSymbol(0, TString("name"), type);
original->setLine(getTestSourceLoc());
original->setInternal(true);
TIntermTyped *copy = original->deepCopy();
checkSymbolCopy(original, copy);
checkTestSourceLoc(copy->getLine());
}
// Check that the deep copy of a constant union node is an actual copy with the same attributes as
// the original.
TEST_F(IntermNodeTest, DeepCopyConstantUnionNode)
{
TType type(EbtInt, EbpHigh);
TConstantUnion *constValue = new TConstantUnion[1];
constValue[0].setIConst(101);
TIntermConstantUnion *original = new TIntermConstantUnion(constValue, type);
original->setLine(getTestSourceLoc());
TIntermTyped *copyTyped = original->deepCopy();
TIntermConstantUnion *copy = copyTyped->getAsConstantUnion();
ASSERT_NE(nullptr, copy);
ASSERT_NE(original, copy);
checkTestSourceLoc(copy->getLine());
checkTypeEqualWithQualifiers(original->getType(), copy->getType());
ASSERT_EQ(101, copy->getIConst(0));
}
// Check that the deep copy of a binary node is an actual copy with the same attributes as the
// original. Child nodes also need to be copies with the same attributes as the original children.
TEST_F(IntermNodeTest, DeepCopyBinaryNode)
{
TType type(EbtFloat, EbpHigh);
TIntermBinary *original = new TIntermBinary(EOpAdd, createTestSymbol(), createTestSymbol());
original->setLine(getTestSourceLoc());
TIntermTyped *copyTyped = original->deepCopy();
TIntermBinary *copy = copyTyped->getAsBinaryNode();
ASSERT_NE(nullptr, copy);
ASSERT_NE(original, copy);
checkTestSourceLoc(copy->getLine());
checkTypeEqualWithQualifiers(original->getType(), copy->getType());
checkSymbolCopy(original->getLeft(), copy->getLeft());
checkSymbolCopy(original->getRight(), copy->getRight());
}
// Check that the deep copy of a unary node is an actual copy with the same attributes as the
// original. The child node also needs to be a copy with the same attributes as the original child.
TEST_F(IntermNodeTest, DeepCopyUnaryNode)
{
TType type(EbtFloat, EbpHigh);
TIntermUnary *original = new TIntermUnary(EOpPreIncrement, createTestSymbol());
original->setLine(getTestSourceLoc());
TIntermTyped *copyTyped = original->deepCopy();
TIntermUnary *copy = copyTyped->getAsUnaryNode();
ASSERT_NE(nullptr, copy);
ASSERT_NE(original, copy);
checkTestSourceLoc(copy->getLine());
checkTypeEqualWithQualifiers(original->getType(), copy->getType());
checkSymbolCopy(original->getOperand(), copy->getOperand());
}
// Check that the deep copy of an aggregate node is an actual copy with the same attributes as the
// original. Child nodes also need to be copies with the same attributes as the original children.
TEST_F(IntermNodeTest, DeepCopyAggregateNode)
{
TIntermSequence *originalSeq = new TIntermSequence();
originalSeq->push_back(createTestSymbol());
originalSeq->push_back(createTestSymbol());
originalSeq->push_back(createTestSymbol());
TIntermAggregate *original =
TIntermAggregate::Create(originalSeq->at(0)->getAsTyped()->getType(), EOpMix, originalSeq);
original->setLine(getTestSourceLoc());
TIntermTyped *copyTyped = original->deepCopy();
TIntermAggregate *copy = copyTyped->getAsAggregate();
ASSERT_NE(nullptr, copy);
ASSERT_NE(original, copy);
checkTestSourceLoc(copy->getLine());
checkTypeEqualWithQualifiers(original->getType(), copy->getType());
ASSERT_EQ(original->getSequence()->size(), copy->getSequence()->size());
TIntermSequence::size_type i = 0;
for (auto *copyChild : *copy->getSequence())
{
TIntermNode *originalChild = original->getSequence()->at(i);
checkSymbolCopy(originalChild, copyChild);
++i;
}
}
// Check that the deep copy of a ternary node is an actual copy with the same attributes as the
// original. Child nodes also need to be copies with the same attributes as the original children.
TEST_F(IntermNodeTest, DeepCopyTernaryNode)
{
TType type(EbtFloat, EbpHigh);
TIntermTernary *original = new TIntermTernary(createTestSymbol(TType(EbtBool, EbpUndefined)),
createTestSymbol(), createTestSymbol());
original->setLine(getTestSourceLoc());
TIntermTyped *copyTyped = original->deepCopy();
TIntermTernary *copy = copyTyped->getAsTernaryNode();
ASSERT_NE(nullptr, copy);
ASSERT_NE(original, copy);
checkTestSourceLoc(copy->getLine());
checkTypeEqualWithQualifiers(original->getType(), copy->getType());
checkSymbolCopy(original->getCondition(), copy->getCondition());
checkSymbolCopy(original->getTrueExpression(), copy->getTrueExpression());
checkSymbolCopy(original->getFalseExpression(), copy->getFalseExpression());
}