//===- llvm/unittests/Frontend/OpenMPDirectiveNameParserTest.cpp ----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/ADT/Sequence.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Frontend/OpenMP/DirectiveNameParser.h" #include "llvm/Frontend/OpenMP/OMP.h" #include "gtest/gtest.h" #include #include #include #include #include using namespace llvm; static const omp::DirectiveNameParser &getParser() { static omp::DirectiveNameParser Parser(omp::SourceLanguage::C | omp::SourceLanguage::Fortran); return Parser; } static std::vector tokenize(StringRef S) { std::vector Tokens; using TokenIterator = std::istream_iterator; std::string Copy = S.str(); std::istringstream Stream(Copy); for (auto I = TokenIterator(Stream), E = TokenIterator(); I != E; ++I) Tokens.push_back(*I); return Tokens; } static std::string &prepareParamName(std::string &Name) { for (size_t I = 0, E = Name.size(); I != E; ++I) { // The parameter name must only have alphanumeric characters. if (!isalnum(Name[I])) Name[I] = 'X'; } return Name; } // Test tokenizing. class Tokenize : public testing::TestWithParam {}; static bool isEqual(const SmallVector &A, const std::vector &B) { if (A.size() != B.size()) return false; for (size_t I = 0, E = A.size(); I != E; ++I) { if (A[I] != StringRef(B[I])) return false; } return true; } TEST_P(Tokenize, T) { omp::Directive DirId = GetParam(); StringRef Name = omp::getOpenMPDirectiveName(DirId, omp::FallbackVersion); SmallVector tokens1 = omp::DirectiveNameParser::tokenize(Name); std::vector tokens2 = tokenize(Name); ASSERT_TRUE(isEqual(tokens1, tokens2)); } static std::string getParamName1(const testing::TestParamInfo &Info) { omp::Directive DirId = Info.param; std::string Name = omp::getOpenMPDirectiveName(DirId, omp::FallbackVersion).str(); return prepareParamName(Name); } INSTANTIATE_TEST_SUITE_P(DirectiveNameParserTest, Tokenize, testing::ValuesIn(llvm::enum_seq_inclusive( omp::Directive::First_, omp::Directive::Last_)), getParamName1); // Test parsing of valid names. using ValueType = std::tuple; class ParseValid : public testing::TestWithParam {}; TEST_P(ParseValid, T) { auto [DirId, Version] = GetParam(); if (DirId == omp::Directive::OMPD_unknown) return; std::string Name = omp::getOpenMPDirectiveName(DirId, Version).str(); // Tokenize and parse auto &Parser = getParser(); auto *State = Parser.initial(); ASSERT_TRUE(State != nullptr); std::vector Tokens = tokenize(Name); for (auto &Tok : Tokens) { State = Parser.consume(State, Tok); ASSERT_TRUE(State != nullptr); } ASSERT_EQ(State->Value, DirId); } static std::string getParamName2(const testing::TestParamInfo &Info) { auto [DirId, Version] = Info.param; std::string Name = omp::getOpenMPDirectiveName(DirId, Version).str() + "v" + std::to_string(Version); return prepareParamName(Name); } INSTANTIATE_TEST_SUITE_P( DirectiveNameParserTest, ParseValid, testing::Combine(testing::ValuesIn(llvm::enum_seq_inclusive( omp::Directive::First_, omp::Directive::Last_)), testing::ValuesIn(omp::getOpenMPVersions())), getParamName2); // Test parsing of invalid names class ParseInvalid : public testing::TestWithParam {}; TEST_P(ParseInvalid, T) { std::string Name = GetParam(); auto &Parser = getParser(); auto *State = Parser.initial(); ASSERT_TRUE(State != nullptr); std::vector Tokens = tokenize(Name); for (auto &Tok : Tokens) State = Parser.consume(State, Tok); ASSERT_TRUE(State == nullptr || State->Value == omp::Directive::OMPD_unknown); } namespace { using namespace std; INSTANTIATE_TEST_SUITE_P(DirectiveNameParserTest, ParseInvalid, testing::Values( // Names that contain invalid tokens "bad"s, "target teams invalid"s, "target sections parallel"s, "target teams distribute parallel for wrong"s, // Valid beginning, but not a complete name "begin declare"s, // Complete name with extra tokens "distribute simd target"s)); } // namespace