2 // DataAdapterBaseTest.cs : Defines a base class 'BaseAdapter' that provides the common
4 // 1) Reading a config file containing the
5 // database connection parameters, different
6 // tables and their description, Values that
7 // the tables are populated with.
8 // 2) Retrieves data from these tables (Fills a dataset).
9 // 3) Compares the retrieved values against the ones
10 // contained in the config file.
12 // A class specific to each database (and ODBC) is derived from this class.
13 // These classes contain code specific to different databases (like establishing
14 // a connection, comparing date values, etc).
17 // Satya Sudha K (ksathyasudha@novell.com)
20 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
22 // Permission is hereby granted, free of charge, to any person obtaining
23 // a copy of this software and associated documentation files (the
24 // "Software"), to deal in the Software without restriction, including
25 // without limitation the rights to use, copy, modify, merge, publish,
26 // distribute, sublicense, and/or sell copies of the Software, and to
27 // permit persons to whom the Software is furnished to do so, subject to
28 // the following conditions:
30 // The above copyright notice and this permission notice shall be
31 // included in all copies or substantial portions of the Software.
33 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
34 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
35 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
36 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
37 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
38 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
39 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43 using System.Collections;
46 using System.Xml.XPath;
48 using System.Data.Common;
49 using System.Configuration;
50 using System.Text.RegularExpressions;
52 namespace MonoTests.System.Data {
54 public class BaseAdapter {
56 public IDbConnection con;
57 public IDbCommand cmd;
58 public DbDataAdapter dataAdapter;
59 public DataSet dataset;
60 string [,] setOfChanges;
61 protected XmlNode configDoc;
63 public BaseAdapter (string database)
70 configDoc = (XmlNode) ConfigurationSettings.GetConfig (database);
77 cmd = con.CreateCommand ();
80 // Method that actually runs the entire test : Connects to a database,
81 // retrieves values from different tables, and compares them against
82 // the values that we had entered
83 public void RunTest ()
94 string noOfQueries = null;
99 noOfQueries = ConfigClass.GetElement (configDoc, "queries", "numQueries");
100 int numQueries = Convert.ToInt32 (noOfQueries);
101 string tableName = null;
102 int [] columnNos = null;
104 Console.WriteLine ("\n**** Testing Data Retrieval using datasets*****\n");
106 for (int i = 1; i <= numQueries; i++) {
109 query = ConfigClass.GetElement (configDoc, "queries", "query" + i);
110 query = FrameQuery (query, ref columnNos, ref tableNum);
111 tableName = ConfigClass.GetElement (configDoc, "tables", "table" + tableNum, "name");
112 } catch (XPathException e) {
113 Console.WriteLine (e.Message);
114 continue; // need not return here; try with the next one
118 PopulateDataSetFromTable (query, tableName);
119 } catch (Exception e) {
120 Console.WriteLine ("Table : {0} : Unable to fill the dataset!!!", tableName);
121 Console.WriteLine ("ERROR : " + e.Message);
122 Console.WriteLine ("STACKTRACE : " + e.StackTrace);
126 CompareData (tableNum, setOfChanges, columnNos);
129 string [] columnNames = null;
130 string noOfTables = ConfigClass.GetElement (configDoc, "tables", "numTables");
132 if (noOfTables != null)
133 numTables = Convert.ToInt32 (noOfTables);
135 for (int i = 1; i <= numTables; i++) {
139 tableName = ConfigClass.GetElement (configDoc, "tables", "table" + i, "name");
140 columnNames = ConfigClass.GetColumnNames (configDoc, i);
141 } catch (XPathException e) {
142 Console.WriteLine (e.Message);
143 continue; // need not return here; try with the next one
147 query = "Select " + String.Join (",", columnNames) + " from " + tableName;
148 PopulateDataSetFromTable (query, tableName);
149 } catch (Exception e) {
150 Console.WriteLine ("Table : {0} : Unable to fill the dataset after " +
151 "updating the database!!!", tableName);
152 Console.WriteLine ("ERROR : " + e.Message);
153 Console.WriteLine ("STACKTRACE : " + e.StackTrace);
157 if (dataset == null) {
158 Console.WriteLine ("Unable to populate the dataset!!!");
162 MakeChanges (i, ref errorMsg);
164 if (dataset.HasChanges() == false) {
165 Console.WriteLine ("\nTable : {0} : No Changes for this table in the config file",
169 if (ReconcileChanges (tableName, ref errorMsg) == false) {
170 Console.WriteLine ("Table : {0} : Unable to " +
171 "update the database !!!", tableName);
172 Console.WriteLine (errorMsg);
175 Console.WriteLine ("\nTable : {0} : Updated " +
176 "using datasets", tableName);
180 Console.WriteLine ("\nTable : {0} : Refilling the dataset\n", tableName);
181 // Clear the data in the dataset
183 //Fill again from the database
184 dataAdapter.Fill (dataset, tableName);
185 CompareData (i, setOfChanges, null);
188 } catch (Exception e) {
189 Console.WriteLine ("ERROR : " + e.Message);
190 Console.WriteLine ("STACKTRACE : " + e.StackTrace);
198 public virtual IDataReader QueryUsingStoredProc (IDbCommand cmd,
199 string storedProcName,
203 cmd.CommandType = CommandType.StoredProcedure;
204 cmd.CommandText = storedProcName;
205 IDataReader rdr = null;
207 rdr = cmd.ExecuteReader ();
208 } catch (Exception e) {
209 Console.WriteLine ("Could not execute command : " + cmd.CommandText);
210 Console.WriteLine ("ERROR : " + e.Message);
211 Console.WriteLine ("STACKTRACE : " + e.StackTrace);
218 protected string FrameQuery (string queryStr,
219 ref int [] columnNos,
222 string regexp = "\\b(Select|select) (?<columnList>(COLUMNS|((COLUMN\\d+,)*(COLUMN\\d+)))) from (?<tableName>TABLE\\d+)( order by (?<OrderBy>COLUMN\\d+))*";
223 Match m = Regex.Match (queryStr, regexp, RegexOptions.ExplicitCapture);
226 Console.WriteLine ("Incorrect query format!!!");
233 string tableTag = m.Result ("${tableName}");
234 tableNum = Convert.ToInt32 (tableTag.Replace ("TABLE", ""));
235 string tableName = ConfigClass.GetElement (configDoc, "tables", tableTag.ToLower (), "name");
236 queryStr = queryStr.Replace (tableTag, tableName);
238 for (int i = 0; i < m.Groups.Count; i++) {
240 Group g = m.Groups [i];
241 CaptureCollection cc = g.Captures;
243 for (int j = 0; j < cc.Count; j++) {
245 string matchedVal = cc [j].Value;
247 if (matchedVal.Equals ("COLUMNS")) {
248 string [] columnNames = ConfigClass.GetColumnNames (configDoc, tableNum);
249 queryStr = queryStr.Replace ("COLUMNS", String.Join (",", columnNames));
250 columnNos = new int [columnNames.Length];
251 for (int index = 1; index <= columnNos.Length; index++) {
252 columnNos [index - 1] = index;
254 } else if (matchedVal.StartsWith ("COLUMN")) {
255 // May be a column name or a comma
256 // separated list of columns
257 string [] listOfColumns = matchedVal.Split (',');
259 if (columnNos == null) {
261 columnNos = new int [listOfColumns.Length];
263 foreach (string str in listOfColumns) {
264 int columnNo = Convert.ToInt32 (str.Replace ("COLUMN", ""));
265 columnNos [colIndex++] = columnNo;
269 foreach (string str in listOfColumns) {
270 string columnName = ConfigClass.GetElement (configDoc, "tables",
271 tableTag.ToLower (), str.ToLower (), "name");
272 queryStr = queryStr.Replace (str, columnName);
284 public virtual bool ReconcileChanges (string tableName, ref string errorMsg)
289 public virtual void PopulateDataSetFromTable (string queryStr, string tableName)
294 public virtual void MakeChanges (int tableNum, ref string errorMsg)
296 string numchanges = null;
298 numchanges = ConfigClass.GetElement (configDoc, "values", "table" + tableNum, "changes", "numChanges");
299 } catch (Exception e) {
303 int noChanges = Convert.ToInt32 (numchanges);
304 string tableName = ConfigClass.GetElement (configDoc, "values", "table" + tableNum, "tableName");
305 int numRows = Convert.ToInt32 (ConfigClass.GetElement (configDoc, "values", "table" + tableNum, "numRows"));
306 int numCols = Convert.ToInt32 (ConfigClass.GetElement (configDoc, "values", "table" + tableNum, "numCols"));
307 setOfChanges = new string [numRows,numCols];
309 for (int x = 0; x < numRows; x++)
310 for (int y = 0; y < numCols; y++)
311 setOfChanges [x,y] = null;
315 foreach (DataTable dbTable in dataset.Tables) {
318 if (tableName.Equals (dbTable.TableName))
322 for (int index = 1; index <= noChanges; index++) {
324 string tagname = "change" + index;
325 int row = Convert.ToInt32 (ConfigClass.GetElement (configDoc, "values",
326 "table" + tableNum, "changes", tagname, "row"));
327 int col = Convert.ToInt32 (ConfigClass.GetElement (configDoc, "values",
328 "table" + tableNum, "changes", tagname, "col"));
329 string value = ConfigClass.GetElement (configDoc, "values",
330 "table" + tableNum, "changes", tagname, "value");
331 setOfChanges [row - 1,col - 1] = value;
332 DataRow drow = dataset.Tables [dbTableNo].Rows [row - 1];
333 DataColumn dcol = dataset.Tables [dbTableNo].Columns [col - 1];
334 object dataSetValue = drow [dcol];
336 drow [dcol] = ConvertToType (dataSetValue.GetType (), value, ref errorMsg);
337 } catch (Exception e) {
338 drow [dcol] = DBNull.Value;
343 public virtual object ConvertValue (string value, Type type)
345 return Convert.ChangeType (value, type);
348 void CompareData (int numTable, string [,] setOfChanges, int [] columnNos)
351 string errorMsg = "";
352 string tableName = null;
354 tableName = ConfigClass.GetElement (configDoc, "tables", "table"+numTable, "name");
355 } catch (Exception e) {
356 Console.WriteLine ("ERROR : " + e.Message );
357 Console.WriteLine ("STACKTRACE : " + e.StackTrace );
361 foreach (DataTable dbTable in dataset.Tables) {
362 if (!tableName.Equals (dbTable.TableName))
365 foreach (DataRow datarow in dbTable.Rows) {
367 string columnValue = null;
369 foreach (DataColumn datacolumn in dbTable.Columns) {
372 int columnNo = column;
373 if (columnNos != null) {
374 columnNo = columnNos [column - 1];
376 if ((setOfChanges != null ) && (setOfChanges [row - 1, columnNo - 1] !=null)) {
377 columnValue = setOfChanges [row - 1, columnNo - 1];
380 columnValue = ConfigClass.GetElement (configDoc, "values",
381 "table" + numTable, "row" + row, "column" + columnNo);
382 } catch (Exception e) {
383 Console.WriteLine ("ERROR : " + e.Message);
384 Console.WriteLine ("STACKTRACE : " + e.StackTrace);
389 Console.Write ("Table: {0} : ROW: {1} COL: {2}", tableName, row , columnNo);
391 obj = datarow [datacolumn];
392 } catch (Exception e) {
394 Console.WriteLine ("...FAIL");
395 errorMsg = "ERROR : " + e.Message;
396 errorMsg += "\nSTACKTRACE : " + e.StackTrace;
397 errorMsg += "\nProbably the 'DataType' property returned a wrong type!!";
398 Console.WriteLine (errorMsg);
403 if (AreEqual (obj, columnValue, ref errorMsg)) {
404 Console.WriteLine ("...OK");
406 Console.WriteLine ("...FAIL");
408 if (!errorMsg.Equals ("")) {
409 // There was some exception
410 Console.WriteLine (errorMsg);
413 Console.WriteLine ("Expected : {0} Got: {1}", columnValue, obj);
417 Console.WriteLine ("======================");
422 public virtual object GetValue (IDataReader rdr, int columnIndex)
427 if (rdr.IsDBNull (columnIndex))
430 Type type = rdr.GetFieldType (columnIndex);
432 switch (type.Name.ToLower ()) {
434 case "byte" : value = rdr.GetByte (columnIndex);
436 case "sbyte" : value = rdr.GetInt16 (columnIndex);
438 case "boolean" : value = rdr.GetBoolean (columnIndex);
440 case "int16" : value = rdr.GetInt16 (columnIndex);
443 case "int32" : value = rdr.GetInt32 (columnIndex);
446 case "int64" : value = rdr.GetInt64 (columnIndex);
448 case "single" : value = rdr.GetFloat (columnIndex);
450 case "double" : value = rdr.GetDouble (columnIndex);
453 case "decimal" : value = rdr.GetDecimal (columnIndex);
455 case "datetime": value = rdr.GetDateTime (columnIndex);
457 case "string": value = rdr.GetString (columnIndex);
459 default : value = rdr.GetValue (columnIndex);
467 public virtual object ConvertToType (Type type, string value, ref string errorMsg)
469 if (value.Equals ("null"))
472 switch (Type.GetTypeCode (type)) {
473 case TypeCode.Int16 :
474 return ConvertToInt16 (type, value, ref errorMsg);
475 case TypeCode.Int32 :
476 return ConvertToInt32 (type, value, ref errorMsg);
477 case TypeCode.Int64 :
478 return ConvertToInt64 (type, value, ref errorMsg);
479 case TypeCode.String :
481 case TypeCode.Boolean :
482 return ConvertToBoolean (type, value, ref errorMsg);
484 return ConvertToByte (type, value, ref errorMsg);
485 case TypeCode.DateTime :
486 return ConvertToDateTime (type, value, ref errorMsg);
487 case TypeCode.Decimal :
488 return ConvertToDecimal (type, value, ref errorMsg);
489 case TypeCode.Double :
490 return ConvertToDouble (type, value, ref errorMsg);
491 case TypeCode.Single :
492 return ConvertToSingle (type, value, ref errorMsg);
495 if (type.ToString () == "System.TimeSpan")
496 return ConvertToTimeSpan (type, value, ref errorMsg);
498 return ConvertValue (type, value, ref errorMsg);
501 public virtual Boolean AreEqual (object obj, string value, ref string errorMsg)
504 if (obj.Equals (DBNull.Value) || (value.Equals ("null"))) {
505 if (obj.Equals (DBNull.Value) && value.Equals ("null"))
509 Type objType = obj.GetType ();
510 value = value.Trim ('\'');
511 value = value.Trim ('\"');
512 object valObj = ConvertToType (objType, value, ref errorMsg);
513 return valObj.Equals (obj);
516 public virtual object ConvertValue (Type type, string value, ref string errorMsg)
519 object valObj = null;
522 valObj = Convert.ChangeType (value, type);
523 } catch (InvalidCastException e) {
524 errorMsg = "Cant convert values!! \n";
525 errorMsg += "ERROR : " + e.Message;
526 errorMsg += "\nSTACKTRACE : " + e.StackTrace;
528 } catch (Exception e) {
529 errorMsg = "ERROR : " + e.Message;
530 errorMsg += "\nSTACKTRACE : " + e.StackTrace;
538 public virtual object ConvertToInt16 (Type type, string value, ref string errorMsg)
540 return ConvertValue (type, value, ref errorMsg);
543 public virtual object ConvertToInt32 (Type type, string value, ref string errorMsg)
545 return ConvertValue (type, value, ref errorMsg);
548 public virtual object ConvertToInt64 (Type type, string value, ref string errorMsg)
550 return ConvertValue (type, value, ref errorMsg);
553 public virtual object ConvertToBoolean (Type type, string value, ref string errorMsg)
555 return ConvertValue (type, value, ref errorMsg);
558 public virtual object ConvertToByte (Type type, string value, ref string errorMsg)
560 return ConvertValue (type, value, ref errorMsg);
563 public virtual object ConvertToDateTime (Type type, string value, ref string errorMsg)
565 return ConvertValue (type, value, ref errorMsg);
568 public virtual object ConvertToDecimal (Type type, string value, ref string errorMsg)
570 return ConvertValue (type, value, ref errorMsg);
573 public virtual object ConvertToDouble (Type type, string value, ref string errorMsg)
575 return ConvertValue (type, value, ref errorMsg);
578 public virtual object ConvertToSingle (Type type, string value, ref string errorMsg)
580 return ConvertValue (type, value, ref errorMsg);
583 public virtual object ConvertToTimeSpan (Type type, string value, ref string errorMsg)
585 return ConvertValue (type, value, ref errorMsg);
588 public virtual void GetConnection ()