aboutsummaryrefslogtreecommitdiff
path: root/lldb/unittests/Language/ObjC/ObjCLanguageTest.cpp
blob: 70baa7e6bc13502c05f5cf8e18e87349ae9a4798 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//===-- 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 <optional>

#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<const ObjCLanguage::ObjCMethodName> method =
        ObjCLanguage::ObjCMethodName::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<const ObjCLanguage::ObjCMethodName> method =
        ObjCLanguage::ObjCMethodName::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<const ObjCLanguage::ObjCMethodName> method =
        ObjCLanguage::ObjCMethodName::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<const ObjCLanguage::ObjCMethodName> method =
        ObjCLanguage::ObjCMethodName::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<const ObjCLanguage::ObjCMethodName> strict_method =
        ObjCLanguage::ObjCMethodName::Create(name, /*strict = */ false);
    EXPECT_FALSE(strict_method.has_value());

    std::optional<const ObjCLanguage::ObjCMethodName> lax_method =
        ObjCLanguage::ObjCMethodName::Create(name, /*strict = */ false);
    EXPECT_FALSE(lax_method.has_value());
  }
}