DataAdapterBaseTest.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. //
  2. // DataAdapterBaseTest.cs : Defines a base class 'BaseAdapter' that provides the common
  3. // functionality of :
  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.
  11. //
  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).
  15. //
  16. // Author:
  17. // Satya Sudha K ([email protected])
  18. //
  19. //
  20. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  21. //
  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:
  29. //
  30. // The above copyright notice and this permission notice shall be
  31. // included in all copies or substantial portions of the Software.
  32. //
  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.
  40. //
  41. using System;
  42. using System.Collections;
  43. using System.IO;
  44. using System.Xml;
  45. using System.Xml.XPath;
  46. using System.Data;
  47. using System.Data.Common;
  48. using System.Configuration;
  49. using System.Text.RegularExpressions;
  50. namespace MonoTests.System.Data {
  51. public class BaseAdapter {
  52. public IDbConnection con;
  53. public IDbCommand cmd;
  54. public DbDataAdapter dataAdapter;
  55. public DataSet dataset;
  56. string [,] setOfChanges;
  57. protected XmlNode configDoc;
  58. public BaseAdapter (string database)
  59. {
  60. con = null;
  61. cmd = null;
  62. dataAdapter = null;
  63. dataset = null;
  64. setOfChanges = null;
  65. configDoc = (XmlNode) ConfigurationSettings.GetConfig (database);
  66. }
  67. void CreateCommand ()
  68. {
  69. if (con == null)
  70. return;
  71. cmd = con.CreateCommand ();
  72. }
  73. // Method that actually runs the entire test : Connects to a database,
  74. // retrieves values from different tables, and compares them against
  75. // the values that we had entered
  76. public void RunTest ()
  77. {
  78. GetConnection ();
  79. if (con == null)
  80. return;
  81. CreateCommand ();
  82. if (cmd == null)
  83. return;
  84. string noOfQueries = null;
  85. string errorMsg = "";
  86. string query = null;
  87. try {
  88. noOfQueries = ConfigClass.GetElement (configDoc, "queries", "numQueries");
  89. int numQueries = Convert.ToInt32 (noOfQueries);
  90. string tableName = null;
  91. int [] columnNos = null;
  92. int tableNum = 0;
  93. Console.WriteLine ("\n**** Testing Data Retrieval using datasets*****\n");
  94. for (int i = 1; i <= numQueries; i++) {
  95. errorMsg = "";
  96. try {
  97. query = ConfigClass.GetElement (configDoc, "queries", "query" + i);
  98. query = FrameQuery (query, ref columnNos, ref tableNum);
  99. tableName = ConfigClass.GetElement (configDoc, "tables", "table" + tableNum, "name");
  100. } catch (XPathException e) {
  101. Console.WriteLine (e.Message);
  102. continue; // need not return here; try with the next one
  103. }
  104. try {
  105. PopulateDataSetFromTable (query, tableName);
  106. } catch (Exception e) {
  107. Console.WriteLine ("Table : {0} : Unable to fill the dataset!!!", tableName);
  108. Console.WriteLine ("ERROR : " + e.Message);
  109. Console.WriteLine ("STACKTRACE : " + e.StackTrace);
  110. continue;
  111. }
  112. CompareData (tableNum, setOfChanges, columnNos);
  113. }
  114. string [] columnNames = null;
  115. string noOfTables = ConfigClass.GetElement (configDoc, "tables", "numTables");
  116. int numTables = 0;
  117. if (noOfTables != null)
  118. numTables = Convert.ToInt32 (noOfTables);
  119. for (int i = 1; i <= numTables; i++) {
  120. setOfChanges = null;
  121. try {
  122. tableName = ConfigClass.GetElement (configDoc, "tables", "table" + i, "name");
  123. columnNames = ConfigClass.GetColumnNames (configDoc, i);
  124. } catch (XPathException e) {
  125. Console.WriteLine (e.Message);
  126. continue; // need not return here; try with the next one
  127. }
  128. try {
  129. query = "Select " + String.Join (",", columnNames) + " from " + tableName;
  130. PopulateDataSetFromTable (query, tableName);
  131. } catch (Exception e) {
  132. Console.WriteLine ("Table : {0} : Unable to fill the dataset after " +
  133. "updating the database!!!", tableName);
  134. Console.WriteLine ("ERROR : " + e.Message);
  135. Console.WriteLine ("STACKTRACE : " + e.StackTrace);
  136. continue;
  137. }
  138. if (dataset == null) {
  139. Console.WriteLine ("Unable to populate the dataset!!!");
  140. continue;
  141. }
  142. MakeChanges (i, ref errorMsg);
  143. if (dataset.HasChanges() == false) {
  144. Console.WriteLine ("\nTable : {0} : No Changes for this table in the config file",
  145. tableName);
  146. continue;
  147. } else {
  148. if (ReconcileChanges (tableName, ref errorMsg) == false) {
  149. Console.WriteLine ("Table : {0} : Unable to " +
  150. "update the database !!!", tableName);
  151. Console.WriteLine (errorMsg);
  152. continue;
  153. } else {
  154. Console.WriteLine ("\nTable : {0} : Updated " +
  155. "using datasets", tableName);
  156. }
  157. }
  158. Console.WriteLine ("\nTable : {0} : Refilling the dataset\n", tableName);
  159. // Clear the data in the dataset
  160. dataset.Clear ();
  161. //Fill again from the database
  162. dataAdapter.Fill (dataset, tableName);
  163. CompareData (i, setOfChanges, null);
  164. }
  165. } catch (Exception e) {
  166. Console.WriteLine ("ERROR : " + e.Message);
  167. Console.WriteLine ("STACKTRACE : " + e.StackTrace);
  168. } finally {
  169. con.Close ();
  170. con = null;
  171. }
  172. }
  173. public virtual IDataReader QueryUsingStoredProc (IDbCommand cmd,
  174. string storedProcName,
  175. string paramName)
  176. {
  177. cmd.CommandType = CommandType.StoredProcedure;
  178. cmd.CommandText = storedProcName;
  179. IDataReader rdr = null;
  180. try {
  181. rdr = cmd.ExecuteReader ();
  182. } catch (Exception e) {
  183. Console.WriteLine ("Could not execute command : " + cmd.CommandText);
  184. Console.WriteLine ("ERROR : " + e.Message);
  185. Console.WriteLine ("STACKTRACE : " + e.StackTrace);
  186. return null;
  187. }
  188. return rdr;
  189. }
  190. protected string FrameQuery (string queryStr,
  191. ref int [] columnNos,
  192. ref int tableNum)
  193. {
  194. string regexp = "\\b(Select|select) (?<columnList>(COLUMNS|((COLUMN\\d+,)*(COLUMN\\d+)))) from (?<tableName>TABLE\\d+)( order by (?<OrderBy>COLUMN\\d+))*";
  195. Match m = Regex.Match (queryStr, regexp, RegexOptions.ExplicitCapture);
  196. if (!m.Success) {
  197. Console.WriteLine ("Incorrect query format!!!");
  198. return null;
  199. }
  200. columnNos = null;
  201. while (m.Success) {
  202. string tableTag = m.Result ("${tableName}");
  203. tableNum = Convert.ToInt32 (tableTag.Replace ("TABLE", ""));
  204. string tableName = ConfigClass.GetElement (configDoc, "tables", tableTag.ToLower (), "name");
  205. queryStr = queryStr.Replace (tableTag, tableName);
  206. for (int i = 0; i < m.Groups.Count; i++) {
  207. Group g = m.Groups [i];
  208. CaptureCollection cc = g.Captures;
  209. for (int j = 0; j < cc.Count; j++) {
  210. string matchedVal = cc [j].Value;
  211. if (matchedVal.Equals ("COLUMNS")) {
  212. string [] columnNames = ConfigClass.GetColumnNames (configDoc, tableNum);
  213. queryStr = queryStr.Replace ("COLUMNS", String.Join (",", columnNames));
  214. columnNos = new int [columnNames.Length];
  215. for (int index = 1; index <= columnNos.Length; index++) {
  216. columnNos [index - 1] = index;
  217. }
  218. } else if (matchedVal.StartsWith ("COLUMN")) {
  219. // May be a column name or a comma
  220. // separated list of columns
  221. string [] listOfColumns = matchedVal.Split (',');
  222. if (columnNos == null) {
  223. columnNos = new int [listOfColumns.Length];
  224. int colIndex = 0;
  225. foreach (string str in listOfColumns) {
  226. int columnNo = Convert.ToInt32 (str.Replace ("COLUMN", ""));
  227. columnNos [colIndex++] = columnNo;
  228. }
  229. }
  230. foreach (string str in listOfColumns) {
  231. string columnName = ConfigClass.GetElement (configDoc, "tables",
  232. tableTag.ToLower (), str.ToLower (), "name");
  233. queryStr = queryStr.Replace (str, columnName);
  234. }
  235. }
  236. }
  237. }
  238. m = m.NextMatch ();
  239. }
  240. return queryStr;
  241. }
  242. public virtual bool ReconcileChanges (string tableName, ref string errorMsg)
  243. {
  244. return false;
  245. }
  246. public virtual void PopulateDataSetFromTable (string queryStr, string tableName)
  247. {
  248. return;
  249. }
  250. public virtual void MakeChanges (int tableNum, ref string errorMsg)
  251. {
  252. string numchanges = null;
  253. try {
  254. numchanges = ConfigClass.GetElement (configDoc, "values", "table" + tableNum, "changes", "numChanges");
  255. } catch (Exception e) {
  256. return;
  257. }
  258. int noChanges = Convert.ToInt32 (numchanges);
  259. string tableName = ConfigClass.GetElement (configDoc, "values", "table" + tableNum, "tableName");
  260. int numRows = Convert.ToInt32 (ConfigClass.GetElement (configDoc, "values", "table" + tableNum, "numRows"));
  261. int numCols = Convert.ToInt32 (ConfigClass.GetElement (configDoc, "values", "table" + tableNum, "numCols"));
  262. setOfChanges = new string [numRows,numCols];
  263. for (int x = 0; x < numRows; x++)
  264. for (int y = 0; y < numCols; y++)
  265. setOfChanges [x,y] = null;
  266. int dbTableNo = -1;
  267. foreach (DataTable dbTable in dataset.Tables) {
  268. dbTableNo ++;
  269. if (tableName.Equals (dbTable.TableName))
  270. break;
  271. }
  272. for (int index = 1; index <= noChanges; index++) {
  273. string tagname = "change" + index;
  274. int row = Convert.ToInt32 (ConfigClass.GetElement (configDoc, "values",
  275. "table" + tableNum, "changes", tagname, "row"));
  276. int col = Convert.ToInt32 (ConfigClass.GetElement (configDoc, "values",
  277. "table" + tableNum, "changes", tagname, "col"));
  278. string value = ConfigClass.GetElement (configDoc, "values",
  279. "table" + tableNum, "changes", tagname, "value");
  280. setOfChanges [row - 1,col - 1] = value;
  281. DataRow drow = dataset.Tables [dbTableNo].Rows [row - 1];
  282. DataColumn dcol = dataset.Tables [dbTableNo].Columns [col - 1];
  283. object dataSetValue = drow [dcol];
  284. try {
  285. drow [dcol] = ConvertToType (dataSetValue.GetType (), value, ref errorMsg);
  286. } catch (Exception e) {
  287. drow [dcol] = DBNull.Value;
  288. }
  289. }
  290. }
  291. public virtual object ConvertValue (string value, Type type)
  292. {
  293. return Convert.ChangeType (value, type);
  294. }
  295. void CompareData (int numTable, string [,] setOfChanges, int [] columnNos)
  296. {
  297. int row = 0;
  298. string errorMsg = "";
  299. string tableName = null;
  300. try {
  301. tableName = ConfigClass.GetElement (configDoc, "tables", "table"+numTable, "name");
  302. } catch (Exception e) {
  303. Console.WriteLine ("ERROR : " + e.Message );
  304. Console.WriteLine ("STACKTRACE : " + e.StackTrace );
  305. return;
  306. }
  307. foreach (DataTable dbTable in dataset.Tables) {
  308. if (!tableName.Equals (dbTable.TableName))
  309. continue;
  310. row = 0;
  311. foreach (DataRow datarow in dbTable.Rows) {
  312. row ++;
  313. string columnValue = null;
  314. int column = 0;
  315. foreach (DataColumn datacolumn in dbTable.Columns) {
  316. column ++;
  317. errorMsg = "";
  318. int columnNo = column;
  319. if (columnNos != null) {
  320. columnNo = columnNos [column - 1];
  321. }
  322. if ((setOfChanges != null ) && (setOfChanges [row - 1, columnNo - 1] !=null)) {
  323. columnValue = setOfChanges [row - 1, columnNo - 1];
  324. } else {
  325. try {
  326. columnValue = ConfigClass.GetElement (configDoc, "values",
  327. "table" + numTable, "row" + row, "column" + columnNo);
  328. } catch (Exception e) {
  329. Console.WriteLine ("ERROR : " + e.Message);
  330. Console.WriteLine ("STACKTRACE : " + e.StackTrace);
  331. }
  332. }
  333. object obj = null;
  334. Console.Write ("Table: {0} : ROW: {1} COL: {2}", tableName, row , columnNo);
  335. try {
  336. obj = datarow [datacolumn];
  337. } catch (Exception e) {
  338. Console.WriteLine ("...FAIL");
  339. errorMsg = "ERROR : " + e.Message;
  340. errorMsg += "\nSTACKTRACE : " + e.StackTrace;
  341. errorMsg += "\nProbably the 'DataType' property returned a wrong type!!";
  342. Console.WriteLine (errorMsg);
  343. obj = null;
  344. continue;
  345. }
  346. if (AreEqual (obj, columnValue, ref errorMsg)) {
  347. Console.WriteLine ("...OK");
  348. } else {
  349. Console.WriteLine ("...FAIL");
  350. if (!errorMsg.Equals ("")) {
  351. // There was some exception
  352. Console.WriteLine (errorMsg);
  353. } else {
  354. // Comparison failed
  355. Console.WriteLine ("Expected : {0} Got: {1}", columnValue, obj);
  356. }
  357. }
  358. }
  359. Console.WriteLine ("======================");
  360. }
  361. }
  362. }
  363. public virtual object GetValue (IDataReader rdr, int columnIndex)
  364. {
  365. object value = null;
  366. if (rdr.IsDBNull (columnIndex))
  367. return null;
  368. Type type = rdr.GetFieldType (columnIndex);
  369. switch (type.Name.ToLower ()) {
  370. case "byte" : value = rdr.GetByte (columnIndex);
  371. break;
  372. case "sbyte" : value = rdr.GetInt16 (columnIndex);
  373. break;
  374. case "boolean" : value = rdr.GetBoolean (columnIndex);
  375. break;
  376. case "int16" : value = rdr.GetInt16 (columnIndex);
  377. break;
  378. case "uint16" :
  379. case "int32" : value = rdr.GetInt32 (columnIndex);
  380. break;
  381. case "uint32" :
  382. case "int64" : value = rdr.GetInt64 (columnIndex);
  383. break;
  384. case "single" : value = rdr.GetFloat (columnIndex);
  385. break;
  386. case "double" : value = rdr.GetDouble (columnIndex);
  387. break;
  388. case "uint64" :
  389. case "decimal" : value = rdr.GetDecimal (columnIndex);
  390. break;
  391. case "datetime": value = rdr.GetDateTime (columnIndex);
  392. break;
  393. case "string": value = rdr.GetString (columnIndex);
  394. break;
  395. default : value = rdr.GetValue (columnIndex);
  396. break;
  397. }
  398. return value;
  399. }
  400. public virtual object ConvertToType (Type type, string value, ref string errorMsg)
  401. {
  402. if (value.Equals ("null"))
  403. return DBNull.Value;
  404. switch (Type.GetTypeCode (type)) {
  405. case TypeCode.Int16 :
  406. return ConvertToInt16 (type, value, ref errorMsg);
  407. case TypeCode.Int32 :
  408. return ConvertToInt32 (type, value, ref errorMsg);
  409. case TypeCode.Int64 :
  410. return ConvertToInt64 (type, value, ref errorMsg);
  411. case TypeCode.String :
  412. return value;
  413. case TypeCode.Boolean :
  414. return ConvertToBoolean (type, value, ref errorMsg);
  415. case TypeCode.Byte :
  416. return ConvertToByte (type, value, ref errorMsg);
  417. case TypeCode.DateTime :
  418. return ConvertToDateTime (type, value, ref errorMsg);
  419. case TypeCode.Decimal :
  420. return ConvertToDecimal (type, value, ref errorMsg);
  421. case TypeCode.Double :
  422. return ConvertToDouble (type, value, ref errorMsg);
  423. case TypeCode.Single :
  424. return ConvertToSingle (type, value, ref errorMsg);
  425. }
  426. if (type.ToString () == "System.TimeSpan")
  427. return ConvertToTimeSpan (type, value, ref errorMsg);
  428. return ConvertValue (type, value, ref errorMsg);
  429. }
  430. public virtual Boolean AreEqual (object obj, string value, ref string errorMsg)
  431. {
  432. if (obj.Equals (DBNull.Value) || (value.Equals ("null"))) {
  433. if (obj.Equals (DBNull.Value) && value.Equals ("null"))
  434. return true;
  435. return false;
  436. }
  437. Type objType = obj.GetType ();
  438. value = value.Trim ('\'');
  439. value = value.Trim ('\"');
  440. object valObj = ConvertToType (objType, value, ref errorMsg);
  441. return valObj.Equals (obj);
  442. }
  443. public virtual object ConvertValue (Type type, string value, ref string errorMsg)
  444. {
  445. object valObj = null;
  446. try {
  447. valObj = Convert.ChangeType (value, type);
  448. } catch (InvalidCastException e) {
  449. errorMsg = "Cant convert values!! \n";
  450. errorMsg += "ERROR : " + e.Message;
  451. errorMsg += "\nSTACKTRACE : " + e.StackTrace;
  452. return false;
  453. } catch (Exception e) {
  454. errorMsg = "ERROR : " + e.Message;
  455. errorMsg += "\nSTACKTRACE : " + e.StackTrace;
  456. return false;
  457. }
  458. return valObj;
  459. }
  460. public virtual object ConvertToInt16 (Type type, string value, ref string errorMsg)
  461. {
  462. return ConvertValue (type, value, ref errorMsg);
  463. }
  464. public virtual object ConvertToInt32 (Type type, string value, ref string errorMsg)
  465. {
  466. return ConvertValue (type, value, ref errorMsg);
  467. }
  468. public virtual object ConvertToInt64 (Type type, string value, ref string errorMsg)
  469. {
  470. return ConvertValue (type, value, ref errorMsg);
  471. }
  472. public virtual object ConvertToBoolean (Type type, string value, ref string errorMsg)
  473. {
  474. return ConvertValue (type, value, ref errorMsg);
  475. }
  476. public virtual object ConvertToByte (Type type, string value, ref string errorMsg)
  477. {
  478. return ConvertValue (type, value, ref errorMsg);
  479. }
  480. public virtual object ConvertToDateTime (Type type, string value, ref string errorMsg)
  481. {
  482. return ConvertValue (type, value, ref errorMsg);
  483. }
  484. public virtual object ConvertToDecimal (Type type, string value, ref string errorMsg)
  485. {
  486. return ConvertValue (type, value, ref errorMsg);
  487. }
  488. public virtual object ConvertToDouble (Type type, string value, ref string errorMsg)
  489. {
  490. return ConvertValue (type, value, ref errorMsg);
  491. }
  492. public virtual object ConvertToSingle (Type type, string value, ref string errorMsg)
  493. {
  494. return ConvertValue (type, value, ref errorMsg);
  495. }
  496. public virtual object ConvertToTimeSpan (Type type, string value, ref string errorMsg)
  497. {
  498. return ConvertValue (type, value, ref errorMsg);
  499. }
  500. public virtual void GetConnection ()
  501. {
  502. }
  503. }
  504. }