OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
BasicDataServiceTest.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.IO;
30 using System.Collections.Generic;
31 using log4net.Config;
32 using NUnit.Framework;
33 using NUnit.Framework.Constraints;
34 using OpenMetaverse;
35 using OpenSim.Framework;
36 using OpenSim.Tests.Common;
37 using log4net;
38 using System.Data;
39 using System.Data.Common;
40 using System.Reflection;
41 
42 namespace OpenSim.Data.Tests
43 {
55  public class BasicDataServiceTest<TConn, TService>
56  where TConn : DbConnection, new()
57  where TService : class, new()
58  {
59  protected string m_connStr;
60  private TService m_service;
61  private string m_file;
62 
63  // TODO: Is this in the right place here?
64  // Later: apparently it's not, but does it matter here?
65 // protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
66 
67  protected ILog m_log; // doesn't matter here that it's not static, init to correct type in instance .ctor
68 
70  : this("")
71  {
72  }
73 
74  public BasicDataServiceTest(string conn)
75  {
76  m_connStr = !String.IsNullOrEmpty(conn) ? conn : DefaultTestConns.Get(typeof(TConn));
77 
78  m_log = LogManager.GetLogger(this.GetType());
79  OpenSim.Tests.Common.TestLogging.LogToConsole(); // TODO: Is that right?
80  }
81 
88  protected virtual void InitService(object service)
89  {
90  }
91 
92  [TestFixtureSetUp]
93  public void Init()
94  {
95  // Sorry, some SQLite-specific stuff goes here (not a big deal, as its just some file ops)
96  if (typeof(TConn).Name.StartsWith("Sqlite"))
97  {
98  // SQLite doesn't work on power or z linux
99  if (Directory.Exists("/proc/ppc64") || Directory.Exists("/proc/dasd"))
100  Assert.Ignore();
101 
102  if (Util.IsWindows())
103  Util.LoadArchSpecificWindowsDll("sqlite3.dll");
104 
105  // for SQLite, if no explicit conn string is specified, use a temp file
106  if (String.IsNullOrEmpty(m_connStr))
107  {
108  m_file = Path.GetTempFileName() + ".db";
109  m_connStr = "URI=file:" + m_file + ",version=3";
110  }
111  }
112 
113  if (String.IsNullOrEmpty(m_connStr))
114  {
115  string msg = String.Format("Connection string for {0} is not defined, ignoring tests", typeof(TConn).Name);
116  m_log.Warn(msg);
117  Assert.Ignore(msg);
118  }
119 
120  // Try the connection, ignore tests if Open() fails
121  using (TConn conn = new TConn())
122  {
123  conn.ConnectionString = m_connStr;
124  try
125  {
126  conn.Open();
127  conn.Close();
128  }
129  catch
130  {
131  string msg = String.Format("{0} is unable to connect to the database, ignoring tests", typeof(TConn).Name);
132  m_log.Warn(msg);
133  Assert.Ignore(msg);
134  }
135  }
136 
137  // If we manage to connect to the database with the user
138  // and password above it is our test database, and run
139  // these tests. If anything goes wrong, ignore these
140  // tests.
141  try
142  {
143  m_service = new TService();
144  InitService(m_service);
145  }
146  catch (Exception e)
147  {
148  m_log.Error(e.ToString());
149  Assert.Ignore();
150  }
151  }
152 
153  [TestFixtureTearDown]
154  public void Cleanup()
155  {
156  if (m_service != null)
157  {
158  if (m_service is IDisposable)
159  ((IDisposable)m_service).Dispose();
160  m_service = null;
161  }
162 
163  if (!String.IsNullOrEmpty(m_file) && File.Exists(m_file))
164  File.Delete(m_file);
165  }
166 
167  protected virtual DbConnection Connect()
168  {
169  DbConnection cnn = new TConn();
170  cnn.ConnectionString = m_connStr;
171  cnn.Open();
172  return cnn;
173  }
174 
175  protected virtual void ExecuteSql(string sql)
176  {
177  using (DbConnection dbcon = Connect())
178  {
179  using (DbCommand cmd = dbcon.CreateCommand())
180  {
181  cmd.CommandText = sql;
182  cmd.ExecuteNonQuery();
183  }
184  }
185  }
186 
187  protected delegate bool ProcessRow(IDataReader reader);
188 
189  protected virtual int ExecQuery(string sql, bool bSingleRow, ProcessRow action)
190  {
191  int nRecs = 0;
192  using (DbConnection dbcon = Connect())
193  {
194  using (DbCommand cmd = dbcon.CreateCommand())
195  {
196  cmd.CommandText = sql;
197  CommandBehavior cb = bSingleRow ? CommandBehavior.SingleRow : CommandBehavior.Default;
198  using (DbDataReader rdr = cmd.ExecuteReader(cb))
199  {
200  while (rdr.Read())
201  {
202  nRecs++;
203  if (!action(rdr))
204  break;
205  }
206  }
207  }
208  }
209  return nRecs;
210  }
211 
216  protected virtual void DropTables(params string[] tables)
217  {
218  foreach (string tbl in tables)
219  {
220  try
221  {
222  ExecuteSql("DROP TABLE " + tbl + ";");
223  }catch
224  {
225  }
226  }
227  }
228 
232  protected virtual void ResetMigrations(params string[] stores)
233  {
234  string lst = "";
235  foreach (string store in stores)
236  {
237  string s = "'" + store + "'";
238  if (lst == "")
239  lst = s;
240  else
241  lst += ", " + s;
242  }
243 
244  string sCond = stores.Length > 1 ? ("in (" + lst + ")") : ("=" + lst);
245  try
246  {
247  ExecuteSql("DELETE FROM migrations where name " + sCond);
248  }
249  catch
250  {
251  }
252  }
253 
257  protected virtual void ClearTables(params string[] tables)
258  {
259  foreach (string tbl in tables)
260  {
261  try
262  {
263  ExecuteSql("DELETE FROM " + tbl + ";");
264  }
265  catch
266  {
267  }
268  }
269  }
270  }
271 }
virtual void InitService(object service)
To be overridden in derived classes. Do whatever init with the m_service, like setting the conn strin...
virtual void ResetMigrations(params string[] stores)
Clear tables listed as parameters (without dropping them).
virtual void ClearTables(params string[] tables)
Clear tables listed as parameters (without dropping them).
virtual int ExecQuery(string sql, bool bSingleRow, ProcessRow action)
virtual void DropTables(params string[] tables)
Drop tables (listed as parameters). There is no "DROP IF EXISTS" syntax common for all databases...