| // |
| // 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 ©) |
| { |
| 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()); |
| } |
| |