1 // ConnectionManager.cs - Singleton ConnectionManager class to manage
2 // database connections for test cases.
5 // Sureshkumar T (tsureshkumar@novell.com)
7 // Copyright Novell Inc., and the individuals listed on the
11 // Permission is hereby granted, free of charge, to any person
12 // obtaining a copy of this software and associated documentation
13 // files (the "Software"), to deal in the Software without
14 // restriction, including without limitation the rights to use, copy,
15 // modify, merge, publish, distribute, sublicense, and/or sell copies
16 // of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
26 // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 using System.Collections.Generic;
33 using System.Configuration;
35 using System.Data.Common;
37 using System.Data.Odbc;
39 using System.Data.SqlClient;
42 using System.Text.RegularExpressions;
43 using NUnit.Framework;
45 namespace MonoTests.System.Data.Connected
47 public class ConnectionManager
49 private static ConnectionManager instance;
50 private ConnectionHolder<SqlConnection> sql;
52 private const string OdbcEnvVar = "SYSTEM_DATA_ODBC";
53 private const string SqlEnvVar = "SYSTEM_DATA_MSSQL";
55 private ConnectionManager ()
57 //Environment.SetEnvironmentVariable(OdbcEnvVar, @"mysql-odbc|Driver={MySQL ODBC 5.3 Unicode Driver};server=127.0.0.1;uid=sa;pwd=qwerty123;");
58 //Environment.SetEnvironmentVariable(SqlEnvVar, @"sqlserver-tds|server=127.0.0.1;database=master;user id=sa;password=qwerty123");
60 // Generate a random db name
61 DatabaseName = "monotest" + Guid.NewGuid().ToString().Substring(0, 7);
63 sql = ConnectionHolder<SqlConnection>.FromEnvVar(SqlEnvVar);
65 CreateMssqlDatabase();
68 odbc = ConnectionHolder<OdbcConnection>.FromEnvVar(OdbcEnvVar);
70 CreateMysqlDatabase();
74 private void CreateMssqlDatabase()
76 DBHelper.ExecuteNonQuery(sql.Connection, $"CREATE DATABASE [{DatabaseName}]");
77 sql.Connection.ChangeDatabase(DatabaseName);
79 string query = File.ReadAllText(@"Test/ProviderTests/sql/sqlserver.sql");
81 var queries = SplitSqlStatements(query);
82 foreach (var subQuery in queries)
84 DBHelper.ExecuteNonQuery(sql.Connection, subQuery);
89 private void CreateMysqlDatabase()
91 DBHelper.ExecuteNonQuery(odbc.Connection, $"CREATE DATABASE {DatabaseName}");
92 odbc.Connection.ChangeDatabase(DatabaseName);
93 odbc.ConnectionString += $"database={DatabaseName}";
95 string query = File.ReadAllText("Test/ProviderTests/sql/MySQL_5.sql");
97 var groups = query.Replace("delimiter ", "")
98 .Split(new[] { "//\n" }, StringSplitOptions.RemoveEmptyEntries);
100 foreach (var subQuery in groups[0].Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries).Concat(groups.Skip(1)))
102 DBHelper.ExecuteNonQuery(odbc.Connection, subQuery);
107 private void DropMssqlDatabase()
109 sql.Connection.ChangeDatabase("master");
110 string query = $"ALTER DATABASE [{DatabaseName}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;\nDROP DATABASE [{DatabaseName}]";
111 DBHelper.ExecuteNonQuery(sql.Connection, query);
115 private void DropMysqlDatabase()
117 string query = $"DROP DATABASE [{DatabaseName}]";
118 DBHelper.ExecuteNonQuery(odbc.Connection, query);
122 // Split SQL script by "GO" statements
123 private static IEnumerable<string> SplitSqlStatements(string sqlScript)
125 var statements = Regex.Split(sqlScript,
126 $@"^[\t ]*GO[\t ]*\d*[\t ]*(?:--.*)?$",
127 RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);
128 return statements.Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Trim(' ', '\r', '\n'));
131 public static ConnectionManager Instance => instance ?? (instance = new ConnectionManager());
133 public string DatabaseName { get; }
137 private ConnectionHolder<OdbcConnection> odbc;
139 public ConnectionHolder<OdbcConnection> Odbc
144 Assert.Ignore($"{OdbcEnvVar} environment variable is not set");
150 public ConnectionHolder<SqlConnection> Sql
155 Assert.Ignore($"{SqlEnvVar} environment variable is not set");
162 sql?.CloseConnection();
164 odbc?.CloseConnection();
169 public class ConnectionHolder<TConnection> where TConnection : DbConnection
171 private TConnection connection;
173 public EngineConfig EngineConfig { get; }
175 public TConnection Connection
179 if (!(connection.State == ConnectionState.Closed ||
180 connection.State == ConnectionState.Broken))
182 connection.ConnectionString = ConnectionString;
188 public void CloseConnection()
190 if (connection != null && connection.State != ConnectionState.Closed)
194 public string ConnectionString { get; set; }
196 public ConnectionHolder(EngineConfig engineConfig, DbProviderFactory dbProviderFactory, string connectionString)
198 EngineConfig = engineConfig;
199 connection = (TConnection)dbProviderFactory.CreateConnection();
200 ConnectionString = connectionString;
203 public static ConnectionHolder<TConnection> FromEnvVar(string envVarName)
206 throw new NotImplementedException ();
208 string variable = Environment.GetEnvironmentVariable(envVarName) ?? string.Empty;
209 var envParts = variable.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
210 if (envParts.Length == 0 || string.IsNullOrEmpty(envParts[0]))
213 string connectionName = envParts[0];
214 string connectionString = variable.Remove(0, envParts[0].Length + 1);
216 ConnectionConfig[] connections = null;
219 connections = (ConnectionConfig[]) ConfigurationManager.GetSection("providerTests");
226 foreach (ConnectionConfig connConfig in connections)
228 if (connConfig.Name != connectionName)
231 DbProviderFactory factory = DbProviderFactories.GetFactory(connConfig.Factory);
232 return new ConnectionHolder<TConnection>(connConfig.Engine, factory, connectionString);
234 throw new InvalidOperationException($"Connection {connectionName} not found");