1 // ForeignKeyConstraintTest.cs - NUnit Test Cases for [explain here]
4 // Franklin Wise (gracenote@earthlink.net)
5 // Martin Willemoes Hansen (mwh@sysrq.dk)
8 // (C) 2003 Martin Willemoes Hansen
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using NUnit.Framework;
38 namespace MonoTests.System.Data
41 public class ForeignKeyConstraintTest
45 //NOTE: fk constraints only work when the table is part of a DataSet
48 public void GetReady()
54 table = new DataTable("TestTable");
55 table.Columns.Add("Col1",typeof(int));
56 table.Columns.Add("Col2",typeof(int));
57 table.Columns.Add("Col3",typeof(int));
59 _ds.Tables.Add(table);
61 table = new DataTable("TestTable2");
62 table.Columns.Add("Col1",typeof(int));
63 table.Columns.Add("Col2",typeof(int));
64 table.Columns.Add("Col3",typeof(int));
66 _ds.Tables.Add(table);
70 // Tests ctor (string, DataColumn, DataColumn)
74 DataTable Table = _ds.Tables [0];
76 Assert.AreEqual (0, Table.Constraints.Count, "test#01");
77 Table = _ds.Tables [1];
78 Assert.AreEqual (0, Table.Constraints.Count, "test#02");
80 // ctor (string, DataColumn, DataColumn
81 ForeignKeyConstraint Constraint = new ForeignKeyConstraint ("test", _ds.Tables [0].Columns [2], _ds.Tables [1].Columns [0]);
82 Table = _ds.Tables [1];
83 Table.Constraints.Add (Constraint);
85 Assert.AreEqual (1, Table.Constraints.Count, "test#03");
86 Assert.AreEqual ("test", Table.Constraints [0].ConstraintName, "test#04");
87 Assert.AreEqual (typeof (ForeignKeyConstraint), Table.Constraints [0].GetType (), "test#05");
89 Table = _ds.Tables [0];
90 Assert.AreEqual (1, Table.Constraints.Count, "test#06");
91 Assert.AreEqual ("Constraint1", Table.Constraints [0].ConstraintName, "test#07");
92 Assert.AreEqual (typeof (UniqueConstraint), Table.Constraints [0].GetType (), "test#08");
95 // Tests ctor (DataColumn, DataColumn)
99 DataTable Table = _ds.Tables [0];
101 Assert.AreEqual (0, Table.Constraints.Count, "test#01");
102 Table = _ds.Tables [1];
103 Assert.AreEqual (0, Table.Constraints.Count, "test#02");
105 // ctor (string, DataColumn, DataColumn
106 ForeignKeyConstraint Constraint = new ForeignKeyConstraint (_ds.Tables [0].Columns [2], _ds.Tables [1].Columns [0]);
107 Table = _ds.Tables [1];
108 Table.Constraints.Add (Constraint);
110 Assert.AreEqual (1, Table.Constraints.Count, "test#03");
111 Assert.AreEqual ("Constraint1", Table.Constraints [0].ConstraintName, "test#04");
112 Assert.AreEqual (typeof (ForeignKeyConstraint), Table.Constraints [0].GetType (), "test#05");
114 Table = _ds.Tables [0];
115 Assert.AreEqual (1, Table.Constraints.Count, "test#06");
116 Assert.AreEqual ("Constraint1", Table.Constraints [0].ConstraintName, "test#07");
117 Assert.AreEqual (typeof (UniqueConstraint), Table.Constraints [0].GetType (), "test#08");
120 // Test ctor (DataColumn [], DataColumn [])
124 DataTable Table = _ds.Tables [0];
126 Assert.AreEqual (0, Table.Constraints.Count, "test#01");
127 Table = _ds.Tables [1];
128 Assert.AreEqual (0, Table.Constraints.Count, "test#02");
130 DataColumn [] Cols1 = new DataColumn [2];
131 Cols1 [0] = _ds.Tables [0].Columns [1];
132 Cols1 [1] = _ds.Tables [0].Columns [2];
134 DataColumn [] Cols2 = new DataColumn [2];
135 Cols2 [0] = _ds.Tables [1].Columns [0];
136 Cols2 [1] = _ds.Tables [1].Columns [1];
138 ForeignKeyConstraint Constraint = new ForeignKeyConstraint (Cols1, Cols2);
139 Table = _ds.Tables [1];
140 Table.Constraints.Add (Constraint);
142 Assert.AreEqual (1, Table.Constraints.Count, "test#03");
143 Assert.AreEqual ("Constraint1", Table.Constraints [0].ConstraintName, "test#04");
144 Assert.AreEqual (typeof (ForeignKeyConstraint), Table.Constraints [0].GetType (), "test#05");
146 Table = _ds.Tables [0];
147 Assert.AreEqual (1, Table.Constraints.Count, "test#06");
148 Assert.AreEqual ("Constraint1", Table.Constraints [0].ConstraintName, "test#07");
149 Assert.AreEqual (typeof (UniqueConstraint), Table.Constraints [0].GetType (), "test#08");
153 // Tests ctor (string, DataColumn [], DataColumn [])
157 DataTable Table = _ds.Tables [0];
159 Assert.AreEqual (0, Table.Constraints.Count, "test#01");
160 Table = _ds.Tables [1];
161 Assert.AreEqual (0, Table.Constraints.Count, "test#02");
163 DataColumn [] Cols1 = new DataColumn [2];
164 Cols1 [0] = _ds.Tables [0].Columns [1];
165 Cols1 [1] = _ds.Tables [0].Columns [2];
167 DataColumn [] Cols2 = new DataColumn [2];
168 Cols2 [0] = _ds.Tables [1].Columns [0];
169 Cols2 [1] = _ds.Tables [1].Columns [1];
171 ForeignKeyConstraint Constraint = new ForeignKeyConstraint ("Test", Cols1, Cols2);
172 Table = _ds.Tables [1];
173 Table.Constraints.Add (Constraint);
175 Assert.AreEqual (1, Table.Constraints.Count, "test#03");
176 Assert.AreEqual ("Test", Table.Constraints [0].ConstraintName, "test#04");
177 Assert.AreEqual (typeof (ForeignKeyConstraint), Table.Constraints [0].GetType (), "test#05");
179 Table = _ds.Tables [0];
180 Assert.AreEqual (1, Table.Constraints.Count, "test#06");
181 Assert.AreEqual ("Constraint1", Table.Constraints [0].ConstraintName, "test#07");
182 Assert.AreEqual (typeof (UniqueConstraint), Table.Constraints [0].GetType (), "test#08");
186 public void TestCtor5()
188 DataTable table1 = new DataTable ("Table1");
189 DataTable table2 = new DataTable ("Table2");
190 DataSet dataSet = new DataSet();
191 dataSet.Tables.Add (table1);
192 dataSet.Tables.Add (table2);
193 DataColumn column1 = new DataColumn ("col1");
194 DataColumn column2 = new DataColumn ("col2");
195 DataColumn column3 = new DataColumn ("col3");
196 table1.Columns.Add (column1);
197 table1.Columns.Add (column2);
198 table1.Columns.Add (column3);
199 DataColumn column4 = new DataColumn ("col4");
200 DataColumn column5 = new DataColumn ("col5");
201 DataColumn column6 = new DataColumn ("col6");
202 table2.Columns.Add (column4);
203 table2.Columns.Add (column5);
204 table2.Columns.Add (column6);
205 string []parentColumnNames = {"col1", "col2", "col3"};
206 string []childColumnNames = {"col4", "col5", "col6"};
207 string parentTableName = "table1";
209 // Create a ForeingKeyConstraint Object using the constructor
210 // ForeignKeyConstraint (string, string, string[], string[], AcceptRejectRule, Rule, Rule);
211 ForeignKeyConstraint fkc = new ForeignKeyConstraint ("hello world", parentTableName, parentColumnNames, childColumnNames, AcceptRejectRule.Cascade, Rule.Cascade, Rule.Cascade); // Assert that the Constraint object does not belong to any table yet
213 DataTable tmp = fkc.Table;
214 Assert.Fail ("When table is null, get_Table causes an InvalidOperationException.");
215 } catch (NullReferenceException) { // actually .NET throws this (bug)
216 } catch (InvalidOperationException) {
219 Constraint []constraints = new Constraint[3];
220 constraints [0] = new UniqueConstraint (column1);
221 constraints [1] = new UniqueConstraint (column2);
222 constraints [2] = fkc;
224 // Try to add the constraint to ConstraintCollection of the DataTable through Add()
226 table2.Constraints.Add (fkc);
227 throw new ApplicationException ("An Exception was expected");
229 // LAMESPEC : spec says InvalidConstraintException but throws this
230 catch (NullReferenceException) {
233 #if false // FIXME: Here this test crashes under MS.NET.
234 // OK - So AddRange() is the only way!
235 table2.Constraints.AddRange (constraints);
236 // After AddRange(), Check the properties of ForeignKeyConstraint object
237 Assert.IsTrue(fkc.RelatedColumns [0].ColumnName.Equals ("col1"), "#A04");
238 Assert.IsTrue(fkc.RelatedColumns [1].ColumnName.Equals ("col2"), "#A05");
239 Assert.IsTrue(fkc.RelatedColumns [2].ColumnName.Equals ("col3"), "#A06");
240 Assert.IsTrue(fkc.Columns [0].ColumnName.Equals ("col4"), "#A07");
241 Assert.IsTrue(fkc.Columns [1].ColumnName.Equals ("col5"), "#A08");
242 Assert.IsTrue(fkc.Columns [2].ColumnName.Equals ("col6"), "#A09");
244 // Try to add columns with names which do not exist in the table
245 parentColumnNames [2] = "noColumn";
246 ForeignKeyConstraint foreignKeyConstraint = new ForeignKeyConstraint ("hello world", parentTableName, parentColumnNames, childColumnNames, AcceptRejectRule.Cascade, Rule.Cascade, Rule.Cascade);
247 constraints [0] = new UniqueConstraint (column1);
248 constraints [1] = new UniqueConstraint (column2);
249 constraints [2] = foreignKeyConstraint;
251 table2.Constraints.AddRange (constraints);
252 throw new ApplicationException ("An Exception was expected");
254 catch (ArgumentException e) {
256 catch (InvalidConstraintException e){ // Could not test on ms.net, as ms.net does not reach here so far.
259 #if false // FIXME: Here this test crashes under MS.NET.
260 // Check whether the child table really contains the foreign key constraint named "hello world"
261 Assert.IsTrue(table2.Constraints.Contains ("hello world"), "#A11 ");
267 // If Childs and parents are in same table
269 public void KeyBetweenColumns ()
271 DataTable Table = _ds.Tables [0];
273 Assert.AreEqual (0, Table.Constraints.Count, "test#01");
274 Table = _ds.Tables [1];
275 Assert.AreEqual (0, Table.Constraints.Count, "test#02");
278 ForeignKeyConstraint Constraint = new ForeignKeyConstraint ("Test", _ds.Tables [0].Columns [0], _ds.Tables [0].Columns [2]);
279 Table = _ds.Tables [0];
280 Table.Constraints.Add (Constraint);
282 Assert.AreEqual (2, Table.Constraints.Count, "test#03");
283 Assert.AreEqual ("Constraint1", Table.Constraints [0].ConstraintName, "test#04");
284 Assert.AreEqual (typeof (UniqueConstraint), Table.Constraints [0].GetType (), "test#05");
285 Assert.AreEqual ("Test", Table.Constraints [1].ConstraintName, "test#04");
286 Assert.AreEqual (typeof (ForeignKeyConstraint), Table.Constraints [1].GetType (), "test#05");
291 public void CtorExceptions ()
293 ForeignKeyConstraint fkc;
295 DataTable localTable = new DataTable();
296 localTable.Columns.Add("Col1",typeof(int));
297 localTable.Columns.Add("Col2",typeof(bool));
302 fkc = new ForeignKeyConstraint((DataColumn)null,(DataColumn)null);
303 Assert.Fail("Assert.Failed to throw ArgumentNullException.");
305 catch (NullReferenceException) {}
306 catch (AssertionException exc) {throw exc;}
307 catch (Exception exc)
309 Assert.Fail("A1: Wrong Exception type. " + exc.ToString());
312 //zero length collection
315 fkc = new ForeignKeyConstraint(new DataColumn[]{},new DataColumn[]{});
316 Assert.Fail("B1: Assert.Failed to throw ArgumentException.");
318 catch (ArgumentException) {}
319 catch (AssertionException exc) {throw exc;}
320 catch (Exception exc)
322 Assert.Fail("A2: Wrong Exception type. " + exc.ToString());
328 fkc = new ForeignKeyConstraint(_ds.Tables[0].Columns[0], localTable.Columns[0]);
329 Assert.Fail("Assert.Failed to throw InvalidOperationException.");
331 catch (InvalidOperationException) {}
332 catch (AssertionException exc) {throw exc;}
333 catch (Exception exc)
335 Assert.Fail("A3: Wrong Exception type. " + exc.ToString());
340 fkc = new ForeignKeyConstraint(_ds.Tables[0].Columns[0], localTable.Columns[1]);
341 Assert.Fail("Assert.Failed to throw InvalidConstraintException.");
343 // tables in different datasets
344 catch (InvalidOperationException) {}
346 // Cannot create a Key from Columns that belong to
350 fkc = new ForeignKeyConstraint(new DataColumn [] {_ds.Tables[0].Columns[0], _ds.Tables[0].Columns[1]}, new DataColumn [] {localTable.Columns[1], _ds.Tables[1].Columns [0]});
351 Assert.Fail("Assert.Failed to throw InvalidOperationException.");
353 catch (InvalidConstraintException) {}
354 catch (AssertionException exc) {throw exc;}
358 public void CtorExceptions2 ()
360 DataColumn col = new DataColumn("MyCol1",typeof(int));
362 ForeignKeyConstraint fkc;
364 //Columns must belong to a Table
367 fkc = new ForeignKeyConstraint(col, _ds.Tables[0].Columns[0]);
368 Assert.Fail("FTT1: Assert.Failed to throw ArgumentException.");
370 catch (ArgumentException) {}
371 catch (AssertionException exc) {throw exc;}
372 // catch (Exception exc)
374 // Assert.Fail("WET1: Wrong Exception type. " + exc.ToString());
377 //Columns must belong to the same table
378 //InvalidConstraintException
380 DataColumn [] difTable = new DataColumn [] {_ds.Tables[0].Columns[2],
381 _ds.Tables[1].Columns[0]};
384 fkc = new ForeignKeyConstraint(difTable,new DataColumn[] {
385 _ds.Tables[0].Columns[1],
386 _ds.Tables[0].Columns[0]});
388 Assert.Fail("FTT2: Assert.Failed to throw InvalidConstraintException.");
390 catch (InvalidConstraintException) {}
391 catch (AssertionException exc) {throw exc;}
392 catch (Exception exc)
394 Assert.Fail("WET2: Wrong Exception type. " + exc.ToString());
398 //parent columns and child columns should be the same length
400 DataColumn [] twoCol =
401 new DataColumn [] {_ds.Tables[0].Columns[0],_ds.Tables[0].Columns[1]};
406 fkc = new ForeignKeyConstraint(twoCol,
407 new DataColumn[] { _ds.Tables[0].Columns[0]});
409 Assert.Fail("FTT3: Assert.Failed to throw ArgumentException.");
411 catch (ArgumentException) {}
412 catch (AssertionException exc) {throw exc;}
413 catch (Exception exc)
415 Assert.Fail("WET3: Wrong Exception type. " + exc.ToString());
418 //InvalidOperation: Parent and child are the same column.
421 fkc = new ForeignKeyConstraint( _ds.Tables[0].Columns[0],
422 _ds.Tables[0].Columns[0] );
424 Assert.Fail("FTT4: Assert.Failed to throw InvalidOperationException.");
426 catch (InvalidOperationException) {}
427 catch (AssertionException exc) {throw exc;}
428 catch (Exception exc)
430 Assert.Fail("WET4: Wrong Exception type. " + exc.ToString());
436 public void EqualsAndHashCode()
438 DataTable tbl = _ds.Tables[0];
439 DataTable tbl2 = _ds.Tables[1];
441 ForeignKeyConstraint fkc = new ForeignKeyConstraint(
442 new DataColumn[] {tbl.Columns[0], tbl.Columns[1]} ,
443 new DataColumn[] {tbl2.Columns[0], tbl2.Columns[1]} );
445 ForeignKeyConstraint fkc2 = new ForeignKeyConstraint(
446 new DataColumn[] {tbl.Columns[0], tbl.Columns[1]} ,
447 new DataColumn[] {tbl2.Columns[0], tbl2.Columns[1]} );
449 ForeignKeyConstraint fkcDiff =
450 new ForeignKeyConstraint( tbl.Columns[1], tbl.Columns[2]);
452 Assert.IsTrue( fkc.Equals(fkc2) , "Equals Assert.IsTrue.Failed. 1");
453 Assert.IsTrue( fkc2.Equals(fkc) , "Equals Assert.IsTrue.Failed. 2");
454 Assert.IsTrue( fkc.Equals(fkc) , "Equals Assert.IsTrue.Failed. 3");
456 Assert.IsTrue( fkc.Equals(fkcDiff) == false , "Equals Assert.IsTrue.Failed diff. 1");
458 //Assert.IsTrue( "Hash Code Assert.IsTrue.Failed. 1", fkc.GetHashCode() == fkc2.GetHashCode() );
459 Assert.IsTrue( fkc.GetHashCode() != fkcDiff.GetHashCode() , "Hash Code Assert.IsTrue.Failed. 2");
464 [ExpectedException (typeof (ArgumentException))]
465 public void ViolationTest ()
467 DataTable parent = _ds.Tables [0];
468 DataTable child = _ds.Tables [1];
470 parent.Rows.Add (new object [] {1, 1, 1});
471 child.Rows.Add (new object [] {2, 2, 2});
474 child.Constraints.Add (new ForeignKeyConstraint ( parent.Columns [0],
478 // clear the rows for further testing
484 public void NoViolationTest ()
486 DataTable parent = _ds.Tables [0];
487 DataTable child = _ds.Tables [1];
489 parent.Rows.Add (new object [] {1, 1, 1});
490 child.Rows.Add (new object [] {2, 2, 2});
493 _ds.EnforceConstraints = false;
494 child.Constraints.Add (new ForeignKeyConstraint ( parent.Columns [0],
498 // clear the rows for further testing
500 _ds.EnforceConstraints = true;
505 public void ModifyParentKeyBeforeAcceptChanges ()
507 DataSet ds1 = new DataSet();
508 DataTable t1= ds1.Tables.Add ("t1");
509 DataTable t2= ds1.Tables.Add ("t2");
510 t1.Columns.Add ("col1", typeof (int));
511 t2.Columns.Add ("col2", typeof (int));
512 ds1.Relations.Add ("fk", t1.Columns [0], t2.Columns [0]);
514 t1.Rows.Add (new object[] {10});
515 t2.Rows.Add (new object [] {10});
518 Assert.IsTrue((int)t2.Rows [0][0] == 20, "#1");
522 // https://bugzilla.novell.com/show_bug.cgi?id=650402
523 public void ForeignKey_650402 ()
525 DataSet data = new DataSet ();
526 DataTable parent = new DataTable ("parent");
527 DataColumn pk = parent.Columns.Add ("PK");
528 DataTable child = new DataTable ("child");
529 DataColumn fk = child.Columns.Add ("FK");
531 data.Tables.Add (parent);
532 data.Tables.Add (child);
533 data.Relations.Add (pk, fk);
535 parent.Rows.Add ("value");
536 child.Rows.Add ("value");
537 data.AcceptChanges ();
538 child.Rows[0].Delete ();
539 parent.Rows[0][0] = "value2";
541 data.EnforceConstraints = false;
542 data.EnforceConstraints = true;