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;
36 using System.Data.Odbc;
37 using System.Data.SqlClient;
40 using System.Text.RegularExpressions;
41 using NUnit.Framework;
43 namespace MonoTests.System.Data.Connected
45 public class ConnectionManager
47 private static ConnectionManager instance;
48 private ConnectionHolder<OdbcConnection> odbc;
49 private ConnectionHolder<SqlConnection> sql;
51 private const string OdbcEnvVar = "SYSTEM_DATA_ODBC";
52 private const string SqlEnvVar = "SYSTEM_DATA_MSSQL";
54 private ConnectionManager ()
56 //Environment.SetEnvironmentVariable(OdbcEnvVar, @"mysql-odbc|Driver={MySQL ODBC 5.3 Unicode Driver};server=127.0.0.1;uid=sa;pwd=qwerty123;");
57 //Environment.SetEnvironmentVariable(SqlEnvVar, @"sqlserver-tds|server=127.0.0.1;database=master;user id=sa;password=qwerty123");
59 // Generate a random db name
60 DatabaseName = "monotest" + Guid.NewGuid().ToString().Substring(0, 7);
62 sql = ConnectionHolder<SqlConnection>.FromEnvVar(SqlEnvVar);
64 CreateMssqlDatabase();
66 odbc = ConnectionHolder<OdbcConnection>.FromEnvVar(OdbcEnvVar);
68 CreateMysqlDatabase();
71 private void CreateMssqlDatabase()
73 DBHelper.ExecuteNonQuery(sql.Connection, $"CREATE DATABASE [{DatabaseName}]");
74 sql.Connection.ChangeDatabase(DatabaseName);
76 string query = File.ReadAllText(@"Test/ProviderTests/sql/sqlserver.sql");
78 var queries = SplitSqlStatements(query);
79 foreach (var subQuery in queries)
81 DBHelper.ExecuteNonQuery(sql.Connection, subQuery);
85 private void CreateMysqlDatabase()
87 DBHelper.ExecuteNonQuery(odbc.Connection, $"CREATE DATABASE {DatabaseName}");
88 odbc.Connection.ChangeDatabase(DatabaseName);
89 odbc.ConnectionString += $"database={DatabaseName}";
91 string query = File.ReadAllText("Test/ProviderTests/sql/MySQL_5.sql");
93 var groups = query.Replace("delimiter ", "")
94 .Split(new[] { "//\n" }, StringSplitOptions.RemoveEmptyEntries);
96 foreach (var subQuery in groups[0].Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries).Concat(groups.Skip(1)))
98 DBHelper.ExecuteNonQuery(odbc.Connection, subQuery);
102 private void DropMssqlDatabase()
104 sql.Connection.ChangeDatabase("master");
105 string query = $"ALTER DATABASE [{DatabaseName}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;\nDROP DATABASE [{DatabaseName}]";
106 DBHelper.ExecuteNonQuery(sql.Connection, query);
109 private void DropMysqlDatabase()
111 string query = $"DROP DATABASE [{DatabaseName}]";
112 DBHelper.ExecuteNonQuery(odbc.Connection, query);
115 // Split SQL script by "GO" statements
116 private static IEnumerable<string> SplitSqlStatements(string sqlScript)
118 var statements = Regex.Split(sqlScript,
119 $@"^[\t ]*GO[\t ]*\d*[\t ]*(?:--.*)?$",
120 RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);
121 return statements.Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Trim(' ', '\r', '\n'));
124 public static ConnectionManager Instance => instance ?? (instance = new ConnectionManager());
126 public string DatabaseName { get; }
128 public ConnectionHolder<OdbcConnection> Odbc
133 Assert.Ignore($"{OdbcEnvVar} environment variable is not set");
138 public ConnectionHolder<SqlConnection> Sql
143 Assert.Ignore($"{SqlEnvVar} environment variable is not set");
150 sql?.CloseConnection();
151 odbc?.CloseConnection();
155 public class ConnectionHolder<TConnection> where TConnection : DbConnection
157 private TConnection connection;
159 public EngineConfig EngineConfig { get; }
161 public TConnection Connection
165 if (!(connection.State == ConnectionState.Closed ||
166 connection.State == ConnectionState.Broken))
168 connection.ConnectionString = ConnectionString;
174 public void CloseConnection()
176 if (connection != null && connection.State != ConnectionState.Closed)
180 public string ConnectionString { get; set; }
182 public ConnectionHolder(EngineConfig engineConfig, DbProviderFactory dbProviderFactory, string connectionString)
184 EngineConfig = engineConfig;
185 connection = (TConnection)dbProviderFactory.CreateConnection();
186 ConnectionString = connectionString;
189 public static ConnectionHolder<TConnection> FromEnvVar(string envVarName)
191 string variable = Environment.GetEnvironmentVariable(envVarName) ?? string.Empty;
192 var envParts = variable.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
193 if (envParts.Length == 0 || string.IsNullOrEmpty(envParts[0]))
196 string connectionName = envParts[0];
197 string connectionString = variable.Remove(0, envParts[0].Length + 1);
199 ConnectionConfig[] connections = null;
202 connections = (ConnectionConfig[]) ConfigurationManager.GetSection("providerTests");
209 foreach (ConnectionConfig connConfig in connections)
211 if (connConfig.Name != connectionName)
214 DbProviderFactory factory = DbProviderFactories.GetFactory(connConfig.Factory);
215 return new ConnectionHolder<TConnection>(connConfig.Engine, factory, connectionString);
217 throw new InvalidOperationException($"Connection {connectionName} not found");