//===-- ObjCLanguageTest.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 "Plugins/Language/ObjC/ObjCLanguage.h" #include "lldb/lldb-enumerations.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include #include "llvm/ADT/StringRef.h" using namespace lldb_private; TEST(ObjCLanguage, MethodNameParsing) { struct TestCase { llvm::StringRef input; llvm::StringRef full_name_sans_category; llvm::StringRef class_name; llvm::StringRef class_name_with_category; llvm::StringRef category; llvm::StringRef selector; }; TestCase strict_cases[] = { {"-[MyClass mySelector:]", "", "MyClass", "MyClass", "", "mySelector:"}, {"+[MyClass mySelector:]", "", "MyClass", "MyClass", "", "mySelector:"}, {"-[MyClass(my_category) mySelector:]", "-[MyClass mySelector:]", "MyClass", "MyClass(my_category)", "my_category", "mySelector:"}, {"+[MyClass(my_category) mySelector:]", "+[MyClass mySelector:]", "MyClass", "MyClass(my_category)", "my_category", "mySelector:"}, }; TestCase lax_cases[] = { {"[MyClass mySelector:]", "", "MyClass", "MyClass", "", "mySelector:"}, {"[MyClass(my_category) mySelector:]", "[MyClass mySelector:]", "MyClass", "MyClass(my_category)", "my_category", "mySelector:"}, }; // First, be strict for (const auto &test : strict_cases) { std::optional method = ObjCLanguage::MethodName::Create(test.input, /*strict = */ true); EXPECT_TRUE(method.has_value()); EXPECT_EQ(test.full_name_sans_category, method->GetFullNameWithoutCategory()); EXPECT_EQ(test.class_name, method->GetClassName()); EXPECT_EQ(test.class_name_with_category, method->GetClassNameWithCategory()); EXPECT_EQ(test.category, method->GetCategory()); EXPECT_EQ(test.selector, method->GetSelector()); } // We should make sure strict parsing does not accept lax cases for (const auto &test : lax_cases) { std::optional method = ObjCLanguage::MethodName::Create(test.input, /*strict = */ true); EXPECT_FALSE(method.has_value()); } // All strict cases should work when not lax for (const auto &test : strict_cases) { std::optional method = ObjCLanguage::MethodName::Create(test.input, /*strict = */ false); EXPECT_TRUE(method.has_value()); EXPECT_EQ(test.full_name_sans_category, method->GetFullNameWithoutCategory()); EXPECT_EQ(test.class_name, method->GetClassName()); EXPECT_EQ(test.class_name_with_category, method->GetClassNameWithCategory()); EXPECT_EQ(test.category, method->GetCategory()); EXPECT_EQ(test.selector, method->GetSelector()); } // Make sure non-strict parsing works for (const auto &test : lax_cases) { std::optional method = ObjCLanguage::MethodName::Create(test.input, /*strict = */ false); EXPECT_TRUE(method.has_value()); EXPECT_EQ(test.full_name_sans_category, method->GetFullNameWithoutCategory()); EXPECT_EQ(test.class_name, method->GetClassName()); EXPECT_EQ(test.class_name_with_category, method->GetClassNameWithCategory()); EXPECT_EQ(test.category, method->GetCategory()); EXPECT_EQ(test.selector, method->GetSelector()); } } TEST(ObjCLanguage, InvalidMethodNameParsing) { // Tests that we correctly reject malformed function names llvm::StringRef test_cases[] = {"+[Uh oh!", "-[Definitely not...", "[Nice try ] :)", "+MaybeIfYouSquintYourEyes]", "?[Tricky]", "+[]", "-[]", "[]"}; for (const auto &name : test_cases) { std::optional strict_method = ObjCLanguage::MethodName::Create(name, /*strict = */ false); EXPECT_FALSE(strict_method.has_value()); std::optional lax_method = ObjCLanguage::MethodName::Create(name, /*strict = */ false); EXPECT_FALSE(lax_method.has_value()); } }