1 //===-- TestOptionValue.cpp -------- -------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Interpreter/OptionValues.h"
10 #include "gmock/gmock.h"
11 #include "gtest/gtest.h"
13 using namespace lldb_private
;
17 virtual void Invoke() const {}
18 void operator()() const { Invoke(); }
21 ~Callback() = default;
24 class MockCallback final
: public Callback
{
26 MOCK_CONST_METHOD0(Invoke
, void());
29 // Test a single-value class.
30 TEST(OptionValueString
, DeepCopy
) {
31 OptionValueString str
;
32 str
.SetValueFromString("ab");
34 MockCallback callback
;
35 str
.SetValueChangedCallback([&callback
] { callback(); });
36 EXPECT_CALL(callback
, Invoke());
38 auto copy_sp
= str
.DeepCopy(nullptr);
40 // Test that the base class data members are copied/set correctly.
42 ASSERT_EQ(copy_sp
->GetParent().get(), nullptr);
43 ASSERT_TRUE(copy_sp
->OptionWasSet());
44 ASSERT_EQ(copy_sp
->GetValueAs
<llvm::StringRef
>(), "ab");
46 // Trigger the callback.
47 copy_sp
->SetValueFromString("c", eVarSetOperationAppend
);
48 ASSERT_EQ(copy_sp
->GetValueAs
<llvm::StringRef
>(), "abc");
51 // Test an aggregate class.
52 TEST(OptionValueArgs
, DeepCopy
) {
54 args
.SetValueFromString("A B");
56 MockCallback callback
;
57 args
.SetValueChangedCallback([&callback
] { callback(); });
58 EXPECT_CALL(callback
, Invoke());
60 auto copy_sp
= args
.DeepCopy(nullptr);
62 // Test that the base class data members are copied/set correctly.
64 ASSERT_EQ(copy_sp
->GetParent(), nullptr);
65 ASSERT_TRUE(copy_sp
->OptionWasSet());
67 auto *args_copy_ptr
= copy_sp
->GetAsArgs();
68 ASSERT_EQ(args_copy_ptr
->GetSize(), 2U);
69 ASSERT_EQ((*args_copy_ptr
)[0]->GetParent(), copy_sp
);
70 ASSERT_EQ((*args_copy_ptr
)[0]->GetValueAs
<llvm::StringRef
>(), "A");
71 ASSERT_EQ((*args_copy_ptr
)[1]->GetParent(), copy_sp
);
72 ASSERT_EQ((*args_copy_ptr
)[1]->GetValueAs
<llvm::StringRef
>(), "B");
74 // Trigger the callback.
75 copy_sp
->SetValueFromString("C", eVarSetOperationAppend
);
76 ASSERT_TRUE(args_copy_ptr
);
77 ASSERT_EQ(args_copy_ptr
->GetSize(), 3U);
78 ASSERT_EQ((*args_copy_ptr
)[2]->GetValueAs
<llvm::StringRef
>(), "C");
81 class TestProperties
: public OptionValueProperties
{
83 static std::shared_ptr
<TestProperties
> CreateGlobal() {
84 auto props_sp
= std::make_shared
<TestProperties
>();
85 const bool is_global
= false;
87 auto dict_sp
= std::make_shared
<OptionValueDictionary
>(1 << eTypeUInt64
);
88 props_sp
->AppendProperty("dict", "", is_global
, dict_sp
);
90 auto file_list_sp
= std::make_shared
<OptionValueFileSpecList
>();
91 props_sp
->AppendProperty("file-list", "", is_global
, file_list_sp
);
95 void SetDictionaryChangedCallback(const MockCallback
&callback
) {
96 SetValueChangedCallback(m_dict_index
, [&callback
] { callback(); });
99 void SetFileListChangedCallback(const MockCallback
&callback
) {
100 SetValueChangedCallback(m_file_list_index
, [&callback
] { callback(); });
103 OptionValueDictionary
*GetDictionary() {
104 return GetPropertyAtIndexAsOptionValueDictionary(m_dict_index
);
107 OptionValueFileSpecList
*GetFileList() {
108 return GetPropertyAtIndexAsOptionValueFileSpecList(m_file_list_index
);
112 lldb::OptionValueSP
Clone() const override
{
113 return std::make_shared
<TestProperties
>(*this);
116 uint32_t m_dict_index
= 0;
117 uint32_t m_file_list_index
= 1;
120 // Test a user-defined propery class.
121 TEST(TestProperties
, DeepCopy
) {
122 auto props_sp
= TestProperties::CreateGlobal();
123 props_sp
->GetDictionary()->SetValueFromString("A=1 B=2");
124 props_sp
->GetFileList()->SetValueFromString("path/to/file");
126 MockCallback callback
;
127 props_sp
->SetDictionaryChangedCallback(callback
);
128 props_sp
->SetFileListChangedCallback(callback
);
129 EXPECT_CALL(callback
, Invoke()).Times(2);
131 auto copy_sp
= props_sp
->DeepCopy(nullptr);
133 // Test that the base class data members are copied/set correctly.
134 ASSERT_TRUE(copy_sp
);
135 ASSERT_EQ(copy_sp
->GetParent(), nullptr);
137 // This cast is safe only if the class overrides Clone().
138 auto *props_copy_ptr
= static_cast<TestProperties
*>(copy_sp
.get());
139 ASSERT_TRUE(props_copy_ptr
);
141 // Test the first child.
142 auto dict_copy_ptr
= props_copy_ptr
->GetDictionary();
143 ASSERT_TRUE(dict_copy_ptr
);
144 ASSERT_EQ(dict_copy_ptr
->GetParent(), copy_sp
);
145 ASSERT_TRUE(dict_copy_ptr
->OptionWasSet());
146 ASSERT_EQ(dict_copy_ptr
->GetNumValues(), 2U);
148 auto value_ptr
= dict_copy_ptr
->GetValueForKey("A");
149 ASSERT_TRUE(value_ptr
);
150 ASSERT_EQ(value_ptr
->GetParent().get(), dict_copy_ptr
);
151 ASSERT_EQ(value_ptr
->GetValueAs
<uint64_t>(), 1U);
153 value_ptr
= dict_copy_ptr
->GetValueForKey("B");
154 ASSERT_TRUE(value_ptr
);
155 ASSERT_EQ(value_ptr
->GetParent().get(), dict_copy_ptr
);
156 ASSERT_EQ(value_ptr
->GetValueAs
<uint64_t>(), 2U);
158 // Test the second child.
159 auto file_list_copy_ptr
= props_copy_ptr
->GetFileList();
160 ASSERT_TRUE(file_list_copy_ptr
);
161 ASSERT_EQ(file_list_copy_ptr
->GetParent(), copy_sp
);
162 ASSERT_TRUE(file_list_copy_ptr
->OptionWasSet());
164 auto file_list_copy
= file_list_copy_ptr
->GetCurrentValue();
165 ASSERT_EQ(file_list_copy
.GetSize(), 1U);
166 ASSERT_EQ(file_list_copy
.GetFileSpecAtIndex(0), FileSpec("path/to/file"));
168 // Trigger the callback first time.
169 dict_copy_ptr
->SetValueFromString("C=3", eVarSetOperationAppend
);
171 // Trigger the callback second time.
172 file_list_copy_ptr
->SetValueFromString("0 another/path",
173 eVarSetOperationReplace
);