xref: /llvm-project/lldb/unittests/Language/ObjC/ObjCLanguageTest.cpp (revision 915256388f865a1a42808f168fc388fccff14eda)
1dc39d98cSAlex Langford //===-- ObjCLanguageTest.cpp ----------------------------------------------===//
2dc39d98cSAlex Langford //
3dc39d98cSAlex Langford // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4dc39d98cSAlex Langford // See https://llvm.org/LICENSE.txt for license information.
5dc39d98cSAlex Langford // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6dc39d98cSAlex Langford //
7dc39d98cSAlex Langford //===----------------------------------------------------------------------===//
8dc39d98cSAlex Langford #include "Plugins/Language/ObjC/ObjCLanguage.h"
9dc39d98cSAlex Langford #include "lldb/lldb-enumerations.h"
10dc39d98cSAlex Langford #include "gmock/gmock.h"
11dc39d98cSAlex Langford #include "gtest/gtest.h"
12dc39d98cSAlex Langford #include <optional>
13dc39d98cSAlex Langford 
14dc39d98cSAlex Langford #include "llvm/ADT/StringRef.h"
15dc39d98cSAlex Langford 
16dc39d98cSAlex Langford using namespace lldb_private;
17dc39d98cSAlex Langford 
TEST(ObjCLanguage,MethodNameParsing)18dc39d98cSAlex Langford TEST(ObjCLanguage, MethodNameParsing) {
19dc39d98cSAlex Langford   struct TestCase {
20dc39d98cSAlex Langford     llvm::StringRef input;
21dc39d98cSAlex Langford     llvm::StringRef full_name_sans_category;
22dc39d98cSAlex Langford     llvm::StringRef class_name;
23dc39d98cSAlex Langford     llvm::StringRef class_name_with_category;
24dc39d98cSAlex Langford     llvm::StringRef category;
25dc39d98cSAlex Langford     llvm::StringRef selector;
26dc39d98cSAlex Langford   };
27dc39d98cSAlex Langford 
28dc39d98cSAlex Langford   TestCase strict_cases[] = {
29dc39d98cSAlex Langford       {"-[MyClass mySelector:]", "", "MyClass", "MyClass", "", "mySelector:"},
30dc39d98cSAlex Langford       {"+[MyClass mySelector:]", "", "MyClass", "MyClass", "", "mySelector:"},
31dc39d98cSAlex Langford       {"-[MyClass(my_category) mySelector:]", "-[MyClass mySelector:]",
32dc39d98cSAlex Langford        "MyClass", "MyClass(my_category)", "my_category", "mySelector:"},
33dc39d98cSAlex Langford       {"+[MyClass(my_category) mySelector:]", "+[MyClass mySelector:]",
34dc39d98cSAlex Langford        "MyClass", "MyClass(my_category)", "my_category", "mySelector:"},
35dc39d98cSAlex Langford   };
36dc39d98cSAlex Langford 
37dc39d98cSAlex Langford   TestCase lax_cases[] = {
38dc39d98cSAlex Langford       {"[MyClass mySelector:]", "", "MyClass", "MyClass", "", "mySelector:"},
39dc39d98cSAlex Langford       {"[MyClass(my_category) mySelector:]", "[MyClass mySelector:]", "MyClass",
40dc39d98cSAlex Langford        "MyClass(my_category)", "my_category", "mySelector:"},
41dc39d98cSAlex Langford   };
42dc39d98cSAlex Langford 
43dc39d98cSAlex Langford   // First, be strict
44dc39d98cSAlex Langford   for (const auto &test : strict_cases) {
45*91525638SAlex Langford     std::optional<const ObjCLanguage::MethodName> method =
46*91525638SAlex Langford         ObjCLanguage::MethodName::Create(test.input, /*strict = */ true);
47*91525638SAlex Langford     EXPECT_TRUE(method.has_value());
48*91525638SAlex Langford     EXPECT_EQ(test.full_name_sans_category,
49*91525638SAlex Langford               method->GetFullNameWithoutCategory());
50*91525638SAlex Langford     EXPECT_EQ(test.class_name, method->GetClassName());
51dc39d98cSAlex Langford     EXPECT_EQ(test.class_name_with_category,
52*91525638SAlex Langford               method->GetClassNameWithCategory());
53*91525638SAlex Langford     EXPECT_EQ(test.category, method->GetCategory());
54*91525638SAlex Langford     EXPECT_EQ(test.selector, method->GetSelector());
55dc39d98cSAlex Langford   }
56dc39d98cSAlex Langford 
57dc39d98cSAlex Langford   // We should make sure strict parsing does not accept lax cases
58dc39d98cSAlex Langford   for (const auto &test : lax_cases) {
59*91525638SAlex Langford     std::optional<const ObjCLanguage::MethodName> method =
60*91525638SAlex Langford         ObjCLanguage::MethodName::Create(test.input, /*strict = */ true);
61*91525638SAlex Langford     EXPECT_FALSE(method.has_value());
62dc39d98cSAlex Langford   }
63dc39d98cSAlex Langford 
64dc39d98cSAlex Langford   // All strict cases should work when not lax
65dc39d98cSAlex Langford   for (const auto &test : strict_cases) {
66*91525638SAlex Langford     std::optional<const ObjCLanguage::MethodName> method =
67*91525638SAlex Langford         ObjCLanguage::MethodName::Create(test.input, /*strict = */ false);
68*91525638SAlex Langford     EXPECT_TRUE(method.has_value());
69*91525638SAlex Langford     EXPECT_EQ(test.full_name_sans_category,
70*91525638SAlex Langford               method->GetFullNameWithoutCategory());
71*91525638SAlex Langford     EXPECT_EQ(test.class_name, method->GetClassName());
72dc39d98cSAlex Langford     EXPECT_EQ(test.class_name_with_category,
73*91525638SAlex Langford               method->GetClassNameWithCategory());
74*91525638SAlex Langford     EXPECT_EQ(test.category, method->GetCategory());
75*91525638SAlex Langford     EXPECT_EQ(test.selector, method->GetSelector());
76dc39d98cSAlex Langford   }
77dc39d98cSAlex Langford 
78dc39d98cSAlex Langford   // Make sure non-strict parsing works
79dc39d98cSAlex Langford   for (const auto &test : lax_cases) {
80*91525638SAlex Langford     std::optional<const ObjCLanguage::MethodName> method =
81*91525638SAlex Langford         ObjCLanguage::MethodName::Create(test.input, /*strict = */ false);
82*91525638SAlex Langford     EXPECT_TRUE(method.has_value());
83*91525638SAlex Langford     EXPECT_EQ(test.full_name_sans_category,
84*91525638SAlex Langford               method->GetFullNameWithoutCategory());
85*91525638SAlex Langford     EXPECT_EQ(test.class_name, method->GetClassName());
86dc39d98cSAlex Langford     EXPECT_EQ(test.class_name_with_category,
87*91525638SAlex Langford               method->GetClassNameWithCategory());
88*91525638SAlex Langford     EXPECT_EQ(test.category, method->GetCategory());
89*91525638SAlex Langford     EXPECT_EQ(test.selector, method->GetSelector());
90dc39d98cSAlex Langford   }
91dc39d98cSAlex Langford }
92dc39d98cSAlex Langford 
TEST(ObjCLanguage,InvalidMethodNameParsing)93123f939cSCaroline Tice TEST(ObjCLanguage, InvalidMethodNameParsing) {
94dc39d98cSAlex Langford   // Tests that we correctly reject malformed function names
95dc39d98cSAlex Langford 
96dc39d98cSAlex Langford   llvm::StringRef test_cases[] = {"+[Uh oh!",
97dc39d98cSAlex Langford                                   "-[Definitely not...",
98dc39d98cSAlex Langford                                   "[Nice try ] :)",
99dc39d98cSAlex Langford                                   "+MaybeIfYouSquintYourEyes]",
100dc39d98cSAlex Langford                                   "?[Tricky]",
101dc39d98cSAlex Langford                                   "+[]",
102dc39d98cSAlex Langford                                   "-[]",
103dc39d98cSAlex Langford                                   "[]"};
104dc39d98cSAlex Langford 
105dc39d98cSAlex Langford   for (const auto &name : test_cases) {
106*91525638SAlex Langford     std::optional<const ObjCLanguage::MethodName> strict_method =
107*91525638SAlex Langford         ObjCLanguage::MethodName::Create(name, /*strict = */ false);
108*91525638SAlex Langford     EXPECT_FALSE(strict_method.has_value());
109dc39d98cSAlex Langford 
110*91525638SAlex Langford     std::optional<const ObjCLanguage::MethodName> lax_method =
111*91525638SAlex Langford         ObjCLanguage::MethodName::Create(name, /*strict = */ false);
112*91525638SAlex Langford     EXPECT_FALSE(lax_method.has_value());
113dc39d98cSAlex Langford   }
114dc39d98cSAlex Langford }
115