RobotTestingFramework  2.0.1
Robot Testing Framework
DllPluginLoader_impl.h
Go to the documentation of this file.
1 /*
2  * Robot Testing Framework
3  *
4  * Copyright (C) 2015-2019 Istituto Italiano di Tecnologia (IIT)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 
22 #ifndef ROBOTTESTINGFRAMEWORK_DLLPLUGINLOADERIMPL_H
23 #define ROBOTTESTINGFRAMEWORK_DLLPLUGINLOADERIMPL_H
24 
28 
29 #include <string>
30 
34 template <class T>
36 {
37 
38  class Plugin
39  {
40  public:
43  };
44 
45 public:
50  plugin(nullptr)
51  {
52  }
53 
58  {
59  close();
60  }
61 
62 
69  T* open(const std::string filename,
70  const std::string factory_name)
71  {
72 
73  // close any previous loaded plugin
74  close();
75 
76  // create an instance of plugin class and factory
78 
79  // load the test case plugin
80  open_internal(filename, factory_name);
81 
82  if (!plugin->factory.isValid()) {
83  if (plugin->factory.getStatus() == shlibpp::VOCAB('f', 'a', 'c', 't')) {
84  std::string plug_type = (factory_name == ROBOTTESTINGFRAMEWORK_PLUGIN_FACTORY_NAME) ? "test case" : "fixture manager";
85  error = "cannot load plugin " + filename + "; (it is not a Robot Testing Framework " + plug_type + " plugin!)";
86  } else {
87  error = "cannot load plugin " + filename + "; error (" + shlibpp::Vocab::decode(plugin->factory.getStatus()) + ") : " + plugin->factory.getError();
88  }
89  delete plugin;
90  plugin = nullptr;
91  return nullptr;
92  }
93 
94  // TODO: check if this is neccessary!!!
95  //plugin->factory.addRef();
96 
97  // create an instance of the test case from the plugin
98  plugin->test.open(plugin->factory);
99  if (!plugin->test.isValid()) {
100  //error = Asserter::format("cannot create an instance of TestCase from %s", filename.c_str());
101  delete plugin;
102  plugin = nullptr;
103  return nullptr;
104  }
105 
106  return &plugin->test.getContent();
107  }
108 
109 
114  void close()
115  {
116  if (plugin)
117  delete plugin;
118  plugin = nullptr;
119  error.clear();
120  }
121 
126  const std::string& getLastError()
127  {
128  return error;
129  }
130 
131 private:
132  std::string error;
134 
135  void open_internal(const std::string filename,
136  const std::string factory_name)
137  {
138 
139  std::string fullpath;
140 #if defined(_WIN32)
141  std::string ext = ".dll";
142 #else
143  std::string ext = ".so";
144 #endif
145  std::string basename;
146  bool has_ext;
147  if (filename.find(ext) != std::string::npos) {
148  basename = filename.substr(0, filename.size() - ext.size());
149  has_ext = true;
150  } else {
151  basename = filename;
152  has_ext = false;
153  }
154 
155 #if defined(_MSC_VER) && !defined(NDEBUG)
156  // MSVC DEBUG build: try debug name before basic name
157  if (!has_ext) {
158  fullpath = basename + "d" + ext;
159  if (plugin->factory.open(fullpath.c_str(), factory_name.c_str()))
160  return;
161  }
162 #endif
163 
164  // Basic name
165  fullpath = basename + ext;
166  if (plugin->factory.open(fullpath.c_str(), factory_name.c_str()))
167  return;
168 
169 #if defined(_MSC_VER) && defined(NDEBUG)
170  // MSVC RELEASE build: try debug name after basic name
171  if (!has_ext) {
172  fullpath = basename + "d" + ext;
173  if (plugin->factory.open(fullpath.c_str(), factory_name.c_str()))
174  return;
175  }
176 #endif
177 
178 
179 #ifdef CMAKE_INTDIR
180  // On multi-config system, try to find the plugin in the
181  // current config subdirectory
182 
183 # if defined(_MSC_VER) && !defined(NDEBUG)
184  // MSVC DEBUG build: try debug name before basic name
185  if (!has_ext) {
186  fullpath = std::string(CMAKE_INTDIR) + "/" + basename + "d" + ext;
187  if (plugin->factory.open(fullpath.c_str(), factory_name.c_str()))
188  return;
189  }
190 # endif
191 
192  // Basic name
193  fullpath = std::string(CMAKE_INTDIR) + "/" + basename + ext;
194  if (plugin->factory.open(fullpath.c_str(), factory_name.c_str()))
195  return;
196 
197 # if defined(_MSC_VER) && defined(NDEBUG)
198  // MSVC RELEASE build: try debug name after basic name
199  if (!has_ext) {
200  fullpath = std::string(CMAKE_INTDIR) + "/" + basename + "d" + ext;
201  if (plugin->factory.open(fullpath.c_str(), factory_name.c_str()))
202  return;
203  }
204 # endif
205 
206 #endif
207  }
208 };
209 
210 #endif // ROBOTTESTINGFRAMEWORK_DLLPLUGINLOADERIMPL_H
void open_internal(const std::string filename, const std::string factory_name)
shlibpp::SharedLibraryClassFactory< T > factory
#define ROBOTTESTINGFRAMEWORK_PLUGIN_FACTORY_NAME
Definition: Plugin.h:27
void close()
close Unloads the plugin and deletes any allocated memory.
T * open(const std::string filename, const std::string factory_name)
open Loads a generic plugin
constexpr int32_t VOCAB(char a, char b=0, char c=0, char d=0)
Definition: Vocab.h:31
class DllPluginLoaderImpl
Container for an object created using a factory provided by a shared library.
shlibpp::SharedLibraryClass< T > test
virtual ~DllPluginLoaderImpl()
DllPluginLoaderImpl destructor.
A type-safe wrapper for SharedLibraryFactory, committing to creation/destruction of instances of a pa...
DllPluginLoaderImpl()
DllPluginLoaderImpl constructor.
const std::string & getLastError()
getLastError gets the last error if any.
static std::string decode(int code)
Definition: Vocab.h:63