1fd4e5da5Sopenharmony_ci// Copyright (c) 2017 Google Inc. 2fd4e5da5Sopenharmony_ci// 3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License. 5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at 6fd4e5da5Sopenharmony_ci// 7fd4e5da5Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8fd4e5da5Sopenharmony_ci// 9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and 13fd4e5da5Sopenharmony_ci// limitations under the License. 14fd4e5da5Sopenharmony_ci 15fd4e5da5Sopenharmony_ci#include <algorithm> 16fd4e5da5Sopenharmony_ci#include <memory> 17fd4e5da5Sopenharmony_ci#include <utility> 18fd4e5da5Sopenharmony_ci#include <vector> 19fd4e5da5Sopenharmony_ci 20fd4e5da5Sopenharmony_ci#include "gmock/gmock.h" 21fd4e5da5Sopenharmony_ci#include "gtest/gtest.h" 22fd4e5da5Sopenharmony_ci#include "source/opt/instruction.h" 23fd4e5da5Sopenharmony_ci#include "source/opt/instruction_list.h" 24fd4e5da5Sopenharmony_ci 25fd4e5da5Sopenharmony_cinamespace spvtools { 26fd4e5da5Sopenharmony_cinamespace opt { 27fd4e5da5Sopenharmony_cinamespace { 28fd4e5da5Sopenharmony_ci 29fd4e5da5Sopenharmony_ciusing ::testing::ContainerEq; 30fd4e5da5Sopenharmony_ciusing ::testing::ElementsAre; 31fd4e5da5Sopenharmony_ciusing InstructionListTest = ::testing::Test; 32fd4e5da5Sopenharmony_ci 33fd4e5da5Sopenharmony_ci// A class that overrides the destructor, so we can trace it. 34fd4e5da5Sopenharmony_ciclass TestInstruction : public Instruction { 35fd4e5da5Sopenharmony_ci public: 36fd4e5da5Sopenharmony_ci TestInstruction() : Instruction() { created_instructions_.push_back(this); } 37fd4e5da5Sopenharmony_ci 38fd4e5da5Sopenharmony_ci ~TestInstruction() override{ deleted_instructions_.push_back(this); } 39fd4e5da5Sopenharmony_ci 40fd4e5da5Sopenharmony_ci static std::vector<TestInstruction*> created_instructions_; 41fd4e5da5Sopenharmony_ci static std::vector<TestInstruction*> deleted_instructions_; 42fd4e5da5Sopenharmony_ci}; 43fd4e5da5Sopenharmony_ci 44fd4e5da5Sopenharmony_cistd::vector<TestInstruction*> TestInstruction::created_instructions_; 45fd4e5da5Sopenharmony_cistd::vector<TestInstruction*> TestInstruction::deleted_instructions_; 46fd4e5da5Sopenharmony_ci 47fd4e5da5Sopenharmony_ci// Test that the destructor for InstructionList is calling the destructor 48fd4e5da5Sopenharmony_ci// for every element that is in the list. 49fd4e5da5Sopenharmony_ciTEST(InstructionListTest, Destructor) { 50fd4e5da5Sopenharmony_ci InstructionList* list = new InstructionList(); 51fd4e5da5Sopenharmony_ci list->push_back(std::unique_ptr<Instruction>(new Instruction())); 52fd4e5da5Sopenharmony_ci list->push_back(std::unique_ptr<Instruction>(new Instruction())); 53fd4e5da5Sopenharmony_ci delete list; 54fd4e5da5Sopenharmony_ci 55fd4e5da5Sopenharmony_ci // Sorting because we do not care if the order of create and destruction is 56fd4e5da5Sopenharmony_ci // the same. Using generic sort just incase things are changed above. 57fd4e5da5Sopenharmony_ci std::sort(TestInstruction::created_instructions_.begin(), 58fd4e5da5Sopenharmony_ci TestInstruction::created_instructions_.end()); 59fd4e5da5Sopenharmony_ci std::sort(TestInstruction::deleted_instructions_.begin(), 60fd4e5da5Sopenharmony_ci TestInstruction::deleted_instructions_.end()); 61fd4e5da5Sopenharmony_ci EXPECT_THAT(TestInstruction::created_instructions_, 62fd4e5da5Sopenharmony_ci ContainerEq(TestInstruction::deleted_instructions_)); 63fd4e5da5Sopenharmony_ci} 64fd4e5da5Sopenharmony_ci 65fd4e5da5Sopenharmony_ci// Test the |InsertBefore| with a single instruction in the iterator class. 66fd4e5da5Sopenharmony_ci// Need to make sure the elements are inserted in the correct order, and the 67fd4e5da5Sopenharmony_ci// return value points to the correct location. 68fd4e5da5Sopenharmony_ci// 69fd4e5da5Sopenharmony_ci// Comparing addresses to make sure they remain stable, so other data structures 70fd4e5da5Sopenharmony_ci// can have pointers to instructions in InstructionList. 71fd4e5da5Sopenharmony_ciTEST(InstructionListTest, InsertBefore1) { 72fd4e5da5Sopenharmony_ci InstructionList list; 73fd4e5da5Sopenharmony_ci std::vector<Instruction*> inserted_instructions; 74fd4e5da5Sopenharmony_ci for (int i = 0; i < 4; i++) { 75fd4e5da5Sopenharmony_ci std::unique_ptr<Instruction> inst(new Instruction()); 76fd4e5da5Sopenharmony_ci inserted_instructions.push_back(inst.get()); 77fd4e5da5Sopenharmony_ci auto new_element = list.end().InsertBefore(std::move(inst)); 78fd4e5da5Sopenharmony_ci EXPECT_EQ(&*new_element, inserted_instructions.back()); 79fd4e5da5Sopenharmony_ci } 80fd4e5da5Sopenharmony_ci 81fd4e5da5Sopenharmony_ci std::vector<Instruction*> output; 82fd4e5da5Sopenharmony_ci for (auto& i : list) { 83fd4e5da5Sopenharmony_ci output.push_back(&i); 84fd4e5da5Sopenharmony_ci } 85fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ContainerEq(inserted_instructions)); 86fd4e5da5Sopenharmony_ci} 87fd4e5da5Sopenharmony_ci 88fd4e5da5Sopenharmony_ci// Test inserting an entire vector of instructions using InsertBefore. Checking 89fd4e5da5Sopenharmony_ci// the order of insertion and the return value. 90fd4e5da5Sopenharmony_ci// 91fd4e5da5Sopenharmony_ci// Comparing addresses to make sure they remain stable, so other data structures 92fd4e5da5Sopenharmony_ci// can have pointers to instructions in InstructionList. 93fd4e5da5Sopenharmony_ciTEST(InstructionListTest, InsertBefore2) { 94fd4e5da5Sopenharmony_ci InstructionList list; 95fd4e5da5Sopenharmony_ci std::vector<std::unique_ptr<Instruction>> new_instructions; 96fd4e5da5Sopenharmony_ci std::vector<Instruction*> created_instructions; 97fd4e5da5Sopenharmony_ci for (int i = 0; i < 4; i++) { 98fd4e5da5Sopenharmony_ci std::unique_ptr<Instruction> inst(new Instruction()); 99fd4e5da5Sopenharmony_ci created_instructions.push_back(inst.get()); 100fd4e5da5Sopenharmony_ci new_instructions.push_back(std::move(inst)); 101fd4e5da5Sopenharmony_ci } 102fd4e5da5Sopenharmony_ci auto new_element = list.begin().InsertBefore(std::move(new_instructions)); 103fd4e5da5Sopenharmony_ci EXPECT_TRUE(new_instructions.empty()); 104fd4e5da5Sopenharmony_ci EXPECT_EQ(&*new_element, created_instructions.front()); 105fd4e5da5Sopenharmony_ci 106fd4e5da5Sopenharmony_ci std::vector<Instruction*> output; 107fd4e5da5Sopenharmony_ci for (auto& i : list) { 108fd4e5da5Sopenharmony_ci output.push_back(&i); 109fd4e5da5Sopenharmony_ci } 110fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ContainerEq(created_instructions)); 111fd4e5da5Sopenharmony_ci} 112fd4e5da5Sopenharmony_ci 113fd4e5da5Sopenharmony_ci} // namespace 114fd4e5da5Sopenharmony_ci} // namespace opt 115fd4e5da5Sopenharmony_ci} // namespace spvtools 116