brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.8 KiB · c7a56b2 Raw
472 lines · cpp
1 2#include "lldb/Core/PluginManager.h"3 4#include "gtest/gtest.h"5 6using namespace lldb;7using namespace lldb_private;8 9// Mock system runtime plugin create functions.10// Make them all return different values to avoid the ICF optimization11// from combining them into the same function. The values returned12// are not valid SystemRuntime pointers, but they are unique and13// sufficient for testing.14SystemRuntime *CreateSystemRuntimePluginA(Process *process) {15  return (SystemRuntime *)0x1;16}17 18SystemRuntime *CreateSystemRuntimePluginB(Process *process) {19  return (SystemRuntime *)0x2;20}21 22SystemRuntime *CreateSystemRuntimePluginC(Process *process) {23  return (SystemRuntime *)0x3;24}25 26// Test class for testing the PluginManager.27// The PluginManager modifies global state when registering new plugins. This28// class is intended to undo those modifications in the destructor to give each29// test a clean slate with no registered plugins at the start of a test.30class PluginManagerTest : public testing::Test {31public:32  // Remove any pre-registered plugins so we have a known starting point.33  static void SetUpTestSuite() { RemoveAllRegisteredSystemRuntimePlugins(); }34 35  // Add mock system runtime plugins for testing.36  void RegisterMockSystemRuntimePlugins() {37    // Make sure the create functions all have different addresses.38    ASSERT_NE(CreateSystemRuntimePluginA, CreateSystemRuntimePluginB);39    ASSERT_NE(CreateSystemRuntimePluginB, CreateSystemRuntimePluginC);40 41    ASSERT_TRUE(PluginManager::RegisterPlugin("a", "test instance A",42                                              CreateSystemRuntimePluginA));43    ASSERT_TRUE(PluginManager::RegisterPlugin("b", "test instance B",44                                              CreateSystemRuntimePluginB));45    ASSERT_TRUE(PluginManager::RegisterPlugin("c", "test instance C",46                                              CreateSystemRuntimePluginC));47  }48 49  // Remove any plugins added during the tests.50  virtual ~PluginManagerTest() override {51    RemoveAllRegisteredSystemRuntimePlugins();52  }53 54protected:55  std::vector<SystemRuntimeCreateInstance> m_system_runtime_plugins;56 57  static void RemoveAllRegisteredSystemRuntimePlugins() {58    // Enable all currently registered plugins so we can get a handle to59    // their create callbacks in the loop below. Only enabled plugins60    // are returned from the PluginManager Get*CreateCallbackAtIndex apis.61    for (const RegisteredPluginInfo &PluginInfo :62         PluginManager::GetSystemRuntimePluginInfo()) {63      PluginManager::SetSystemRuntimePluginEnabled(PluginInfo.name, true);64    }65 66    // Get a handle to the create call backs for all the registered plugins.67    std::vector<SystemRuntimeCreateInstance> registered_plugin_callbacks;68    SystemRuntimeCreateInstance create_callback = nullptr;69    for (uint32_t idx = 0;70         (create_callback =71              PluginManager::GetSystemRuntimeCreateCallbackAtIndex(idx)) !=72         nullptr;73         ++idx) {74      registered_plugin_callbacks.push_back((create_callback));75    }76 77    // Remove all currently registered plugins.78    for (SystemRuntimeCreateInstance create_callback :79         registered_plugin_callbacks) {80      PluginManager::UnregisterPlugin(create_callback);81    }82  }83};84 85// Test basic register functionality.86TEST_F(PluginManagerTest, RegisterSystemRuntimePlugin) {87  RegisterMockSystemRuntimePlugins();88 89  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(0),90            CreateSystemRuntimePluginA);91 92  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(1),93            CreateSystemRuntimePluginB);94 95  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(2),96            CreateSystemRuntimePluginC);97 98  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(3), nullptr);99}100 101// Test basic un-register functionality.102TEST_F(PluginManagerTest, UnRegisterSystemRuntimePlugin) {103  RegisterMockSystemRuntimePlugins();104 105  ASSERT_TRUE(PluginManager::UnregisterPlugin(CreateSystemRuntimePluginB));106 107  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(0),108            CreateSystemRuntimePluginA);109 110  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(1),111            CreateSystemRuntimePluginC);112 113  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(2), nullptr);114}115 116// Test registered plugin info functionality.117TEST_F(PluginManagerTest, SystemRuntimePluginInfo) {118  RegisterMockSystemRuntimePlugins();119 120  std::vector<RegisteredPluginInfo> plugin_info =121      PluginManager::GetSystemRuntimePluginInfo();122  ASSERT_EQ(plugin_info.size(), 3u);123  ASSERT_EQ(plugin_info[0].name, "a");124  ASSERT_EQ(plugin_info[0].description, "test instance A");125  ASSERT_EQ(plugin_info[0].enabled, true);126  ASSERT_EQ(plugin_info[1].name, "b");127  ASSERT_EQ(plugin_info[1].description, "test instance B");128  ASSERT_EQ(plugin_info[1].enabled, true);129  ASSERT_EQ(plugin_info[2].name, "c");130  ASSERT_EQ(plugin_info[2].description, "test instance C");131  ASSERT_EQ(plugin_info[2].enabled, true);132}133 134// Test basic un-register functionality.135TEST_F(PluginManagerTest, UnRegisterSystemRuntimePluginInfo) {136  RegisterMockSystemRuntimePlugins();137 138  // Initial plugin info has all three registered plugins.139  std::vector<RegisteredPluginInfo> plugin_info =140      PluginManager::GetSystemRuntimePluginInfo();141  ASSERT_EQ(plugin_info.size(), 3u);142 143  ASSERT_TRUE(PluginManager::UnregisterPlugin(CreateSystemRuntimePluginB));144 145  // After un-registering a plugin it should be removed from plugin info.146  plugin_info = PluginManager::GetSystemRuntimePluginInfo();147  ASSERT_EQ(plugin_info.size(), 2u);148  ASSERT_EQ(plugin_info[0].name, "a");149  ASSERT_EQ(plugin_info[0].enabled, true);150  ASSERT_EQ(plugin_info[1].name, "c");151  ASSERT_EQ(plugin_info[1].enabled, true);152}153 154// Test plugin disable functionality.155TEST_F(PluginManagerTest, SystemRuntimePluginDisable) {156  RegisterMockSystemRuntimePlugins();157 158  // Disable plugin should succeed.159  ASSERT_TRUE(PluginManager::SetSystemRuntimePluginEnabled("b", false));160 161  // Disabling a plugin does not remove it from plugin info.162  std::vector<RegisteredPluginInfo> plugin_info =163      PluginManager::GetSystemRuntimePluginInfo();164  ASSERT_EQ(plugin_info.size(), 3u);165  ASSERT_EQ(plugin_info[0].name, "a");166  ASSERT_EQ(plugin_info[0].enabled, true);167  ASSERT_EQ(plugin_info[1].name, "b");168  ASSERT_EQ(plugin_info[1].enabled, false);169  ASSERT_EQ(plugin_info[2].name, "c");170  ASSERT_EQ(plugin_info[2].enabled, true);171 172  // Disabling a plugin does remove it from available plugins.173  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(0),174            CreateSystemRuntimePluginA);175  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(1),176            CreateSystemRuntimePluginC);177  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(2), nullptr);178}179 180// Test plugin disable and enable functionality.181TEST_F(PluginManagerTest, SystemRuntimePluginDisableThenEnable) {182  RegisterMockSystemRuntimePlugins();183 184  // Initially plugin b is available in slot 1.185  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(1),186            CreateSystemRuntimePluginB);187 188  // Disabling it will remove it from available plugins.189  ASSERT_TRUE(PluginManager::SetSystemRuntimePluginEnabled("b", false));190  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(0),191            CreateSystemRuntimePluginA);192  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(1),193            CreateSystemRuntimePluginC);194 195  // We can re-enable the plugin later and it should go back to the original196  // slot.197  ASSERT_TRUE(PluginManager::SetSystemRuntimePluginEnabled("b", true));198  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(0),199            CreateSystemRuntimePluginA);200  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(1),201            CreateSystemRuntimePluginB);202  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(2),203            CreateSystemRuntimePluginC);204 205  // And show up in the plugin info correctly.206  std::vector<RegisteredPluginInfo> plugin_info =207      PluginManager::GetSystemRuntimePluginInfo();208  ASSERT_EQ(plugin_info.size(), 3u);209  ASSERT_EQ(plugin_info[0].name, "a");210  ASSERT_EQ(plugin_info[0].enabled, true);211  ASSERT_EQ(plugin_info[1].name, "b");212  ASSERT_EQ(plugin_info[1].enabled, true);213  ASSERT_EQ(plugin_info[2].name, "c");214  ASSERT_EQ(plugin_info[2].enabled, true);215}216 217// Test calling disable on an already disabled plugin is ok.218TEST_F(PluginManagerTest, SystemRuntimePluginDisableDisabled) {219  RegisterMockSystemRuntimePlugins();220 221  // Initial call to disable the plugin should succeed.222  ASSERT_TRUE(PluginManager::SetSystemRuntimePluginEnabled("b", false));223 224  // The second call should also succeed because the plugin is already disabled.225  ASSERT_TRUE(PluginManager::SetSystemRuntimePluginEnabled("b", false));226 227  // The call to re-enable the plugin should succeed.228  ASSERT_TRUE(PluginManager::SetSystemRuntimePluginEnabled("b", true));229 230  // The second call should also succeed since the plugin is already enabled.231  ASSERT_TRUE(PluginManager::SetSystemRuntimePluginEnabled("b", true));232}233 234// Test calling disable on an already disabled plugin is ok.235TEST_F(PluginManagerTest, SystemRuntimePluginDisableNonExistent) {236  RegisterMockSystemRuntimePlugins();237 238  // Both enable and disable should return false for a non-existent plugin.239  ASSERT_FALSE(240      PluginManager::SetSystemRuntimePluginEnabled("does_not_exist", true));241  ASSERT_FALSE(242      PluginManager::SetSystemRuntimePluginEnabled("does_not_exist", false));243}244 245// Test disabling all plugins and then re-enabling them in a different246// order will restore the original plugin order.247TEST_F(PluginManagerTest, SystemRuntimePluginDisableAll) {248  RegisterMockSystemRuntimePlugins();249 250  // Validate initial state of registered plugins.251  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(0),252            CreateSystemRuntimePluginA);253  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(1),254            CreateSystemRuntimePluginB);255  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(2),256            CreateSystemRuntimePluginC);257 258  // Disable all the active plugins.259  ASSERT_TRUE(PluginManager::SetSystemRuntimePluginEnabled("a", false));260  ASSERT_TRUE(PluginManager::SetSystemRuntimePluginEnabled("b", false));261  ASSERT_TRUE(PluginManager::SetSystemRuntimePluginEnabled("c", false));262 263  // Should have no active plugins.264  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(0), nullptr);265  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(1), nullptr);266  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(2), nullptr);267 268  // And show up in the plugin info correctly.269  std::vector<RegisteredPluginInfo> plugin_info =270      PluginManager::GetSystemRuntimePluginInfo();271  ASSERT_EQ(plugin_info.size(), 3u);272  ASSERT_EQ(plugin_info[0].name, "a");273  ASSERT_EQ(plugin_info[0].enabled, false);274  ASSERT_EQ(plugin_info[1].name, "b");275  ASSERT_EQ(plugin_info[1].enabled, false);276  ASSERT_EQ(plugin_info[2].name, "c");277  ASSERT_EQ(plugin_info[2].enabled, false);278 279  // Enable plugins in reverse order and validate expected indicies.280  // They should show up in the original plugin order.281  ASSERT_TRUE(PluginManager::SetSystemRuntimePluginEnabled("c", true));282  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(0),283            CreateSystemRuntimePluginC);284 285  ASSERT_TRUE(PluginManager::SetSystemRuntimePluginEnabled("a", true));286  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(0),287            CreateSystemRuntimePluginA);288  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(1),289            CreateSystemRuntimePluginC);290 291  ASSERT_TRUE(PluginManager::SetSystemRuntimePluginEnabled("b", true));292  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(0),293            CreateSystemRuntimePluginA);294  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(1),295            CreateSystemRuntimePluginB);296  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(2),297            CreateSystemRuntimePluginC);298}299 300// Test un-registering a disabled plugin works.301TEST_F(PluginManagerTest, UnRegisterDisabledSystemRuntimePlugin) {302  RegisterMockSystemRuntimePlugins();303 304  // Initial plugin info has all three registered plugins.305  std::vector<RegisteredPluginInfo> plugin_info =306      PluginManager::GetSystemRuntimePluginInfo();307  ASSERT_EQ(plugin_info.size(), 3u);308 309  // First disable a plugin, then unregister it. Both should succeed.310  ASSERT_TRUE(PluginManager::SetSystemRuntimePluginEnabled("b", false));311  ASSERT_TRUE(PluginManager::UnregisterPlugin(CreateSystemRuntimePluginB));312 313  // After un-registering a plugin it should be removed from plugin info.314  plugin_info = PluginManager::GetSystemRuntimePluginInfo();315  ASSERT_EQ(plugin_info.size(), 2u);316  ASSERT_EQ(plugin_info[0].name, "a");317  ASSERT_EQ(plugin_info[0].enabled, true);318  ASSERT_EQ(plugin_info[1].name, "c");319  ASSERT_EQ(plugin_info[1].enabled, true);320}321 322// Test un-registering and then re-registering a plugin will change the order of323// loaded plugins.324TEST_F(PluginManagerTest, UnRegisterSystemRuntimePluginChangesOrder) {325  RegisterMockSystemRuntimePlugins();326 327  std::vector<RegisteredPluginInfo> plugin_info =328      PluginManager::GetSystemRuntimePluginInfo();329  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(0),330            CreateSystemRuntimePluginA);331  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(1),332            CreateSystemRuntimePluginB);333  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(2),334            CreateSystemRuntimePluginC);335 336  ASSERT_EQ(plugin_info.size(), 3u);337  ASSERT_EQ(plugin_info[0].name, "a");338  ASSERT_EQ(plugin_info[1].name, "b");339  ASSERT_EQ(plugin_info[2].name, "c");340 341  // Unregister and then registering a plugin puts it at the end of the order342  // list.343  ASSERT_TRUE(PluginManager::UnregisterPlugin(CreateSystemRuntimePluginB));344  ASSERT_TRUE(PluginManager::RegisterPlugin("b", "New test instance B",345                                            CreateSystemRuntimePluginB));346 347  // Check the callback indices match as expected.348  plugin_info = PluginManager::GetSystemRuntimePluginInfo();349  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(0),350            CreateSystemRuntimePluginA);351  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(1),352            CreateSystemRuntimePluginC);353  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(2),354            CreateSystemRuntimePluginB);355 356  // And plugin info should match as well.357  ASSERT_EQ(plugin_info.size(), 3u);358  ASSERT_EQ(plugin_info[0].name, "a");359  ASSERT_EQ(plugin_info[1].name, "c");360  ASSERT_EQ(plugin_info[2].name, "b");361  ASSERT_EQ(plugin_info[2].description, "New test instance B");362 363  // Disabling and re-enabling the "c" plugin should slot it back364  // into the middle of the order. Originally it was last, but after365  // un-registering and re-registering "b" it should now stay in366  // the middle of the order.367  ASSERT_TRUE(PluginManager::SetSystemRuntimePluginEnabled("c", false));368  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(0),369            CreateSystemRuntimePluginA);370  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(1),371            CreateSystemRuntimePluginB);372 373  // And re-enabling374  ASSERT_TRUE(PluginManager::SetSystemRuntimePluginEnabled("c", true));375  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(0),376            CreateSystemRuntimePluginA);377  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(1),378            CreateSystemRuntimePluginC);379  ASSERT_EQ(PluginManager::GetSystemRuntimeCreateCallbackAtIndex(2),380            CreateSystemRuntimePluginB);381}382 383TEST_F(PluginManagerTest, MatchPluginName) {384  PluginNamespace Foo{"foo", nullptr, nullptr};385  RegisteredPluginInfo Bar{"bar", "bar plugin ", true};386  RegisteredPluginInfo Baz{"baz", "baz plugin ", true};387 388  // Empty pattern matches everything.389  ASSERT_TRUE(PluginManager::MatchPluginName("", Foo, Bar));390 391  // Plugin namespace matches all plugins in that namespace.392  ASSERT_TRUE(PluginManager::MatchPluginName("foo", Foo, Bar));393  ASSERT_TRUE(PluginManager::MatchPluginName("foo", Foo, Baz));394 395  // Fully qualified plugin name matches only that plugin.396  ASSERT_TRUE(PluginManager::MatchPluginName("foo.bar", Foo, Bar));397  ASSERT_FALSE(PluginManager::MatchPluginName("foo.baz", Foo, Bar));398 399  // Prefix match should not match.400  ASSERT_FALSE(PluginManager::MatchPluginName("f", Foo, Bar));401  ASSERT_FALSE(PluginManager::MatchPluginName("foo.", Foo, Bar));402  ASSERT_FALSE(PluginManager::MatchPluginName("foo.ba", Foo, Bar));403}404 405TEST_F(PluginManagerTest, JsonFormat) {406  RegisterMockSystemRuntimePlugins();407 408  // We expect the following JSON output:409  // {410  //   "system-runtime": [411  //     {412  //       "enabled": true,413  //       "name": "a"414  //     },415  //     {416  //       "enabled": true,417  //       "name": "b"418  //     },419  //     {420  //       "enabled": true,421  //       "name": "c"422  //     }423  //   ]424  // }425  llvm::json::Object obj = PluginManager::GetJSON();426 427  // We should have a "system-runtime" array in the top-level object.428  llvm::json::Array *maybe_array = obj.getArray("system-runtime");429  ASSERT_TRUE(maybe_array != nullptr);430  auto &array = *maybe_array;431  ASSERT_EQ(array.size(), 3u);432 433  // Check plugin "a" info.434  ASSERT_TRUE(array[0].getAsObject() != nullptr);435  ASSERT_TRUE(array[0].getAsObject()->getString("name") == "a");436  ASSERT_TRUE(array[0].getAsObject()->getBoolean("enabled") == true);437 438  // Check plugin "b" info.439  ASSERT_TRUE(array[1].getAsObject() != nullptr);440  ASSERT_TRUE(array[1].getAsObject()->getString("name") == "b");441  ASSERT_TRUE(array[1].getAsObject()->getBoolean("enabled") == true);442 443  // Check plugin "c" info.444  ASSERT_TRUE(array[2].getAsObject() != nullptr);445  ASSERT_TRUE(array[2].getAsObject()->getString("name") == "c");446  ASSERT_TRUE(array[2].getAsObject()->getBoolean("enabled") == true);447 448  // Disabling a plugin should be reflected in the JSON output.449  ASSERT_TRUE(PluginManager::SetSystemRuntimePluginEnabled("b", false));450  array = *PluginManager::GetJSON().getArray("system-runtime");451  ASSERT_TRUE(array[0].getAsObject()->getBoolean("enabled") == true);452  ASSERT_TRUE(array[1].getAsObject()->getBoolean("enabled") == false);453  ASSERT_TRUE(array[2].getAsObject()->getBoolean("enabled") == true);454 455  // Un-registering a plugin should be reflected in the JSON output.456  ASSERT_TRUE(PluginManager::UnregisterPlugin(CreateSystemRuntimePluginB));457  array = *PluginManager::GetJSON().getArray("system-runtime");458  ASSERT_EQ(array.size(), 2u);459  ASSERT_TRUE(array[0].getAsObject()->getString("name") == "a");460  ASSERT_TRUE(array[1].getAsObject()->getString("name") == "c");461 462  // Filtering the JSON output should only include the matching plugins.463  array =464      *PluginManager::GetJSON("system-runtime.c").getArray("system-runtime");465  ASSERT_EQ(array.size(), 1u);466  ASSERT_TRUE(array[0].getAsObject()->getString("name") == "c");467 468  // Empty JSON output is allowed if there are no matching plugins.469  obj = PluginManager::GetJSON("non-existent-plugin");470  ASSERT_TRUE(obj.empty());471}472