xref: /llvm-project/lldb/unittests/Language/ObjC/ObjCLanguageTest.cpp (revision 915256388f865a1a42808f168fc388fccff14eda)
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-exception
6 //
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 
16 using namespace lldb_private;
17 
TEST(ObjCLanguage,MethodNameParsing)18 TEST(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 strict
44   for (const auto &test : strict_cases) {
45     std::optional<const ObjCLanguage::MethodName> method =
46         ObjCLanguage::MethodName::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 cases
58   for (const auto &test : lax_cases) {
59     std::optional<const ObjCLanguage::MethodName> method =
60         ObjCLanguage::MethodName::Create(test.input, /*strict = */ true);
61     EXPECT_FALSE(method.has_value());
62   }
63 
64   // All strict cases should work when not lax
65   for (const auto &test : strict_cases) {
66     std::optional<const ObjCLanguage::MethodName> method =
67         ObjCLanguage::MethodName::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 works
79   for (const auto &test : lax_cases) {
80     std::optional<const ObjCLanguage::MethodName> method =
81         ObjCLanguage::MethodName::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 
TEST(ObjCLanguage,InvalidMethodNameParsing)93 TEST(ObjCLanguage, InvalidMethodNameParsing) {
94   // Tests that we correctly reject malformed function names
95 
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::MethodName> strict_method =
107         ObjCLanguage::MethodName::Create(name, /*strict = */ false);
108     EXPECT_FALSE(strict_method.has_value());
109 
110     std::optional<const ObjCLanguage::MethodName> lax_method =
111         ObjCLanguage::MethodName::Create(name, /*strict = */ false);
112     EXPECT_FALSE(lax_method.has_value());
113   }
114 }
115