158 lines · cpp
1//===-- ObjCLanguageTest.cpp ----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8#include "Plugins/Language/ObjC/ObjCLanguage.h"9#include "lldb/lldb-enumerations.h"10#include "gmock/gmock.h"11#include "gtest/gtest.h"12#include <optional>13 14#include "llvm/ADT/StringRef.h"15 16using namespace lldb_private;17 18TEST(ObjCLanguage, MethodNameParsing) {19 struct TestCase {20 llvm::StringRef input;21 llvm::StringRef full_name_sans_category;22 llvm::StringRef class_name;23 llvm::StringRef class_name_with_category;24 llvm::StringRef category;25 llvm::StringRef selector;26 };27 28 TestCase strict_cases[] = {29 {"-[MyClass mySelector:]", "", "MyClass", "MyClass", "", "mySelector:"},30 {"+[MyClass mySelector:]", "", "MyClass", "MyClass", "", "mySelector:"},31 {"-[MyClass(my_category) mySelector:]", "-[MyClass mySelector:]",32 "MyClass", "MyClass(my_category)", "my_category", "mySelector:"},33 {"+[MyClass(my_category) mySelector:]", "+[MyClass mySelector:]",34 "MyClass", "MyClass(my_category)", "my_category", "mySelector:"},35 };36 37 TestCase lax_cases[] = {38 {"[MyClass mySelector:]", "", "MyClass", "MyClass", "", "mySelector:"},39 {"[MyClass(my_category) mySelector:]", "[MyClass mySelector:]", "MyClass",40 "MyClass(my_category)", "my_category", "mySelector:"},41 };42 43 // First, be strict44 for (const auto &test : strict_cases) {45 std::optional<const ObjCLanguage::ObjCMethodName> method =46 ObjCLanguage::ObjCMethodName::Create(test.input, /*strict = */ true);47 EXPECT_TRUE(method.has_value());48 EXPECT_EQ(test.full_name_sans_category,49 method->GetFullNameWithoutCategory());50 EXPECT_EQ(test.class_name, method->GetClassName());51 EXPECT_EQ(test.class_name_with_category,52 method->GetClassNameWithCategory());53 EXPECT_EQ(test.category, method->GetCategory());54 EXPECT_EQ(test.selector, method->GetSelector());55 }56 57 // We should make sure strict parsing does not accept lax cases58 for (const auto &test : lax_cases) {59 std::optional<const ObjCLanguage::ObjCMethodName> method =60 ObjCLanguage::ObjCMethodName::Create(test.input, /*strict = */ true);61 EXPECT_FALSE(method.has_value());62 }63 64 // All strict cases should work when not lax65 for (const auto &test : strict_cases) {66 std::optional<const ObjCLanguage::ObjCMethodName> method =67 ObjCLanguage::ObjCMethodName::Create(test.input, /*strict = */ false);68 EXPECT_TRUE(method.has_value());69 EXPECT_EQ(test.full_name_sans_category,70 method->GetFullNameWithoutCategory());71 EXPECT_EQ(test.class_name, method->GetClassName());72 EXPECT_EQ(test.class_name_with_category,73 method->GetClassNameWithCategory());74 EXPECT_EQ(test.category, method->GetCategory());75 EXPECT_EQ(test.selector, method->GetSelector());76 }77 78 // Make sure non-strict parsing works79 for (const auto &test : lax_cases) {80 std::optional<const ObjCLanguage::ObjCMethodName> method =81 ObjCLanguage::ObjCMethodName::Create(test.input, /*strict = */ false);82 EXPECT_TRUE(method.has_value());83 EXPECT_EQ(test.full_name_sans_category,84 method->GetFullNameWithoutCategory());85 EXPECT_EQ(test.class_name, method->GetClassName());86 EXPECT_EQ(test.class_name_with_category,87 method->GetClassNameWithCategory());88 EXPECT_EQ(test.category, method->GetCategory());89 EXPECT_EQ(test.selector, method->GetSelector());90 }91}92 93TEST(ObjCLanguage, InvalidMethodNameParsing) {94 // Tests that we correctly reject malformed function names95 96 llvm::StringRef test_cases[] = {"+[Uh oh!",97 "-[Definitely not...",98 "[Nice try ] :)",99 "+MaybeIfYouSquintYourEyes]",100 "?[Tricky]",101 "+[]",102 "-[]",103 "[]"};104 105 for (const auto &name : test_cases) {106 std::optional<const ObjCLanguage::ObjCMethodName> strict_method =107 ObjCLanguage::ObjCMethodName::Create(name, /*strict = */ false);108 EXPECT_FALSE(strict_method.has_value());109 110 std::optional<const ObjCLanguage::ObjCMethodName> lax_method =111 ObjCLanguage::ObjCMethodName::Create(name, /*strict = */ false);112 EXPECT_FALSE(lax_method.has_value());113 }114}115 116struct ObjCMethodTestCase {117 llvm::StringRef name;118 bool is_valid;119};120 121struct ObjCMethodNameTextFiture122 : public testing::TestWithParam<ObjCMethodTestCase> {};123 124static ObjCMethodTestCase g_objc_method_name_test_cases[] = {125 {"", false},126 {"+[Uh oh!", false},127 {"-[Definitely not...", false},128 {"[Nice try ] :)", false},129 {"+MaybeIfYouSquintYourEyes]", false},130 {"?[Tricky]", false},131 {"[]", false},132 {"-[a", false},133 {"+[a", false},134 {"-]a]", false},135 {"+]a]", false},136 137 // FIXME: should these count as valid?138 {"+[]", true},139 {"-[]", true},140 {"-[[]", true},141 {"+[[]", true},142 {"+[a ]", true},143 {"-[a ]", true},144 145 // Valid names146 {"+[a a]", true},147 {"-[a a]", true},148};149 150TEST_P(ObjCMethodNameTextFiture, TestIsPossibleObjCMethodName) {151 // Tests ObjCLanguage::IsPossibleObjCMethodName152 auto [name, expect_valid] = GetParam();153 EXPECT_EQ(ObjCLanguage::IsPossibleObjCMethodName(name), expect_valid);154}155 156INSTANTIATE_TEST_SUITE_P(ObjCMethodNameTests, ObjCMethodNameTextFiture,157 testing::ValuesIn(g_objc_method_name_test_cases));158