// // 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) { TType type(EbtFloat, EbpHigh); TIntermAggregate *original = new TIntermAggregate(EOpMix); original->setLine(getTestSourceLoc()); TIntermSequence *originalSeq = original->getSequence(); originalSeq->push_back(createTestSymbol()); originalSeq->push_back(createTestSymbol()); originalSeq->push_back(createTestSymbol()); 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 = originalSeq->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()); }