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
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 {.input: "-[MyClass mySelector:]", .full_name_sans_category: "", .class_name: "MyClass", .class_name_with_category: "MyClass", .category: "", .selector: "mySelector:"},
30 {.input: "+[MyClass mySelector:]", .full_name_sans_category: "", .class_name: "MyClass", .class_name_with_category: "MyClass", .category: "", .selector: "mySelector:"},
31 {.input: "-[MyClass(my_category) mySelector:]", .full_name_sans_category: "-[MyClass mySelector:]",
32 .class_name: "MyClass", .class_name_with_category: "MyClass(my_category)", .category: "my_category", .selector: "mySelector:"},
33 {.input: "+[MyClass(my_category) mySelector:]", .full_name_sans_category: "+[MyClass mySelector:]",
34 .class_name: "MyClass", .class_name_with_category: "MyClass(my_category)", .category: "my_category", .selector: "mySelector:"},
35 };
36
37 TestCase lax_cases[] = {
38 {.input: "[MyClass mySelector:]", .full_name_sans_category: "", .class_name: "MyClass", .class_name_with_category: "MyClass", .category: "", .selector: "mySelector:"},
39 {.input: "[MyClass(my_category) mySelector:]", .full_name_sans_category: "[MyClass mySelector:]", .class_name: "MyClass",
40 .class_name_with_category: "MyClass(my_category)", .category: "my_category", .selector: "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(name: 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(name: 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(name: 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(name: 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 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

source code of lldb/unittests/Language/ObjC/ObjCLanguageTest.cpp