changeset 22:1e9bad493475

prevent running unit tests on a non-existing db
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 11 Jul 2018 14:39:59 +0200
parents 2e5d2c69d4f9
children b2ff1cd2907a
files Framework/MySQL/MySQLDatabase.cpp Framework/MySQL/MySQLDatabase.h Framework/MySQL/MySQLParameters.cpp Framework/MySQL/MySQLParameters.h MySQL/Plugins/MySQLIndex.cpp MySQL/UnitTests/UnitTestsMain.cpp
diffstat 6 files changed, 105 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/MySQL/MySQLDatabase.cpp	Tue Jul 10 14:33:05 2018 +0200
+++ b/Framework/MySQL/MySQLDatabase.cpp	Wed Jul 11 14:39:59 2018 +0200
@@ -264,6 +264,18 @@
       throw Orthanc::OrthancException(Orthanc::ErrorCode_Database);
     }
   }
+
+
+  static void CheckAlphanumericString(const std::string& name)
+  {
+    for (size_t i = 0; i < name.length(); i++)
+    {
+      if (!isalnum(name[i]))
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+      }
+    }
+  }
   
 
   bool MySQLDatabase::DoesTableExist(MySQLTransaction& transaction,
@@ -274,14 +286,8 @@
       throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
     }
 
-    for (size_t i = 0; i < name.length(); i++)
-    {
-      if (!isalnum(name[i]))
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
-      }
-    }
-
+    CheckAlphanumericString(name);
+  
     Query query("SELECT COUNT(*) FROM information_schema.TABLES WHERE "
                 "(TABLE_SCHEMA = ${database}) AND (TABLE_NAME = ${table})", true);
     query.SetType("database", ValueType_Utf8String);
@@ -301,6 +307,33 @@
   }
 
 
+  bool MySQLDatabase::DoesDatabaseExist(MySQLTransaction& transaction,
+                                        const std::string& name)
+  {
+    if (mysql_ == NULL)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+
+    CheckAlphanumericString(name);
+  
+    Query query("SELECT COUNT(*) FROM information_schema.SCHEMATA "
+                "WHERE SCHEMA_NAME = ${database}", true);
+    query.SetType("database", ValueType_Utf8String);
+    
+    MySQLStatement statement(*this, query);
+
+    Dictionary args;
+    args.SetUtf8Value("database", name);
+
+    std::auto_ptr<IResult> result(statement.Execute(transaction, args));
+    return (!result->IsDone() &&
+            result->GetFieldsCount() == 1 &&
+            result->GetField(0).GetType() == ValueType_Integer64 &&
+            dynamic_cast<const Integer64Value&>(result->GetField(0)).GetValue() == 1);            
+  }
+
+
   void MySQLDatabase::Execute(const std::string& sql,
                               bool arobaseSeparator)
   {
--- a/Framework/MySQL/MySQLDatabase.h	Tue Jul 10 14:33:05 2018 +0200
+++ b/Framework/MySQL/MySQLDatabase.h	Wed Jul 11 14:39:59 2018 +0200
@@ -72,6 +72,9 @@
     bool DoesTableExist(MySQLTransaction& transaction,
                         const std::string& name);
 
+    bool DoesDatabaseExist(MySQLTransaction& transaction,
+                           const std::string& name);
+
     virtual Dialect GetDialect() const
     {
       return Dialect_MySQL;
--- a/Framework/MySQL/MySQLParameters.cpp	Tue Jul 10 14:33:05 2018 +0200
+++ b/Framework/MySQL/MySQLParameters.cpp	Wed Jul 11 14:39:59 2018 +0200
@@ -125,4 +125,17 @@
   {
     unixSocket_ = socket;
   }
+
+  
+  void MySQLParameters::Format(Json::Value& target) const
+  {
+    target = Json::objectValue;
+    target["Host"] = host_;
+    target["Username"] = username_;
+    target["Password"] = password_;
+    target["Database"] = database_;
+    target["Port"] = port_;
+    target["UnixSocket"] = unixSocket_;
+    target["Lock"] = lock_;
+  }
 }
--- a/Framework/MySQL/MySQLParameters.h	Tue Jul 10 14:33:05 2018 +0200
+++ b/Framework/MySQL/MySQLParameters.h	Wed Jul 11 14:39:59 2018 +0200
@@ -98,5 +98,7 @@
     {
       return lock_;
     }
+
+    void Format(Json::Value& target) const;
   };
 }
--- a/MySQL/Plugins/MySQLIndex.cpp	Tue Jul 10 14:33:05 2018 +0200
+++ b/MySQL/Plugins/MySQLIndex.cpp	Wed Jul 11 14:39:59 2018 +0200
@@ -82,7 +82,14 @@
       db.Open();
 
       MySQLTransaction t(db);
-      db.Execute("DROP DATABASE IF EXISTS " + database, false);
+
+      if (!db.DoesDatabaseExist(t, database))
+      {
+        LOG(ERROR) << "Inexistent database, please create it first: " << database;
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource);
+      }
+      
+      db.Execute("DROP DATABASE " + database, false);
       db.Execute("CREATE DATABASE " + database, false);
       t.Commit();
     }
--- a/MySQL/UnitTests/UnitTestsMain.cpp	Tue Jul 10 14:33:05 2018 +0200
+++ b/MySQL/UnitTests/UnitTestsMain.cpp	Wed Jul 11 14:39:59 2018 +0200
@@ -145,28 +145,50 @@
     return -1;
   }
 
-  if (argc == 5)
+  std::vector<std::string> args;
+  for (int i = 1; i < argc; i++)
   {
-    // UNIX
-    globalParameters_.SetUnixSocket(argv[1]);
-    globalParameters_.SetUsername(argv[2]);
-    globalParameters_.SetPassword(argv[3]);
-    globalParameters_.SetDatabase(argv[4]);
+    // Ignore arguments beginning with "-" to allow passing arguments
+    // to Google Test such as "--gtest_filter="
+    if (argv[i] != NULL &&
+        argv[i][0] != '-')
+    {
+      args.push_back(std::string(argv[i]));
+    }
   }
-  else
-  {
-    // Windows
-    globalParameters_.SetHost(argv[1]);
-    globalParameters_.SetPort(boost::lexical_cast<unsigned int>(argv[2]));
-    globalParameters_.SetUsername(argv[3]);
-    globalParameters_.SetPassword(argv[4]);
-    globalParameters_.SetDatabase(argv[5]);
-  }
-
+  
   ::testing::InitGoogleTest(&argc, argv);
   Orthanc::Logging::Initialize();
   Orthanc::Logging::EnableInfoLevel(true);
   Orthanc::Logging::EnableTraceLevel(true);
+  
+  if (args.size() == 4)
+  {
+    // UNIX flavor
+    globalParameters_.SetUnixSocket(args[0]);
+    globalParameters_.SetUsername(args[1]);
+    globalParameters_.SetPassword(args[2]);
+    globalParameters_.SetDatabase(args[3]);
+  }
+  else if (args.size() == 5)
+  {
+    // Windows flavor
+    globalParameters_.SetHost(args[0]);
+    globalParameters_.SetPort(boost::lexical_cast<unsigned int>(args[1]));
+    globalParameters_.SetUsername(args[2]);
+    globalParameters_.SetPassword(args[3]);
+    globalParameters_.SetDatabase(args[4]);
+  }
+  else
+  {
+    LOG(ERROR) << "Bad number of arguments";
+    return -1;
+  }
+
+  Json::Value config;
+  globalParameters_.Format(config);
+  std::cout << "Parameters of the MySQL connection: " << std::endl
+            << config.toStyledString() << std::endl;
 
   int result = RUN_ALL_TESTS();