[limb-svn] r5952 - 3.x/trunk/limb/active_record/tests/cases

svn at limb-project.com svn at limb-project.com
Wed Jun 6 18:28:07 MSD 2007


Author: pachanga
Date: 2007-06-06 18:28:07 +0400 (Wed, 06 Jun 2007)
New Revision: 5952
URL: http://fisheye.limb-project.com/changelog/limb/?cs=5952

Added:
   3.x/trunk/limb/active_record/tests/cases/lmbARAttributesLazyLoadingTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbARAutoTimesTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbARDirtyTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbAREventHandlersTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbARImportTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbARManyToManyRelationsTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbAROneToManyRelationsTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbAROneToOneRelationsTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbARRelationsDefinitionMethodsTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbARSubclassingTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbARTransactionTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbARValidationTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbARValueObjectTest.class.php
Removed:
   3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordAttributesLazyLoadingTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordAutoTimesTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordDirtyTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordEventHandlersTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordImportTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordManyToManyRelationsTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordOneToManyRelationsTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordOneToOneRelationsTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordRelationsDefinitionMethodsTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordSubclassingTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordTransactionTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordValidationTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordValueObjectTest.class.php
Modified:
   3.x/trunk/limb/active_record/tests/cases/lmbARManyToManyCollectionTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbAROneToManyCollectionTest.class.php
   3.x/trunk/limb/active_record/tests/cases/lmbARRecordSetDecoratorTest.class.php
Log:
-- renaming tests to shorter equivalents: ActiveRecord => AR

Copied: 3.x/trunk/limb/active_record/tests/cases/lmbARAttributesLazyLoadingTest.class.php (from rev 5951, 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordAttributesLazyLoadingTest.class.php)
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbARAttributesLazyLoadingTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbARAttributesLazyLoadingTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -0,0 +1,90 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+lmb_require('limb/active_record/src/lmbActiveRecord.class.php');
+lmb_require('limb/dbal/src/lmbSimpleDb.class.php');
+lmb_require('limb/dbal/src/lmbTableGateway.class.php');
+
+class LazyTestOneTableObject extends lmbActiveRecord
+{
+  protected $_db_table_name = 'test_one_table_object';
+  protected $_lazy_attributes = array('annotation', 'content');
+}
+
+class lmbARAttributesLazyLoadingTest extends UnitTestCase
+{
+  var $conn = null;
+  var $db = null;
+
+  function setUp()
+  {
+    $this->conn = lmbToolkit :: instance()->getDefaultDbConnection();
+    $this->db = new lmbSimpleDb($this->conn);
+    $this->_cleanUp();
+  }
+
+  function tearDown()
+  {
+    $this->_cleanUp();
+  }
+
+  function _cleanUp()
+  {
+    $this->db->delete('test_one_table_object');
+  }
+
+  function testLazyFind()
+  {
+    $object = $this->_createActiveRecord($annotation = 'Some annotation', $content = 'Some content');
+    $object2 = lmbActiveRecord :: findById('LazyTestOneTableObject', $object->getId());
+
+    $this->_checkLazyness($object2, $annotation, $content);
+  }
+
+  function testLazyLoadById()
+  {
+    $object = $this->_createActiveRecord($annotation = 'Some annotation', $content = 'Some content');
+
+    $object2 = new LazyTestOneTableObject();
+    $object2->loadById($object->getId());
+
+    $this->_checkLazyness($object2, $annotation, $content);
+  }
+
+  function testExportIsNotLazy()
+  {
+    $object = $this->_createActiveRecord($annotation = 'Some annotation', $content = 'Some content');
+    $object2 = lmbActiveRecord :: findById('LazyTestOneTableObject', $object->getId());
+    $exported = $object2->export();
+    $this->assertEqual($exported['annotation'], $annotation);
+    $this->assertEqual($exported['content'], $content);
+  }
+
+  protected function _checkLazyness($object, $annotation, $content)
+  {
+    $this->assertTrue($object->hasAttribute('news_date'));
+
+    $this->assertFalse($object->hasAttribute('annotation'));
+    $this->assertEqual($object->getAnnotation(), $annotation);
+    $this->assertTrue($object->hasAttribute('annotation'));
+
+    $this->assertFalse($object->hasAttribute('content'));
+    $this->assertEqual($object->getContent(), $content);
+    $this->assertTrue($object->hasAttribute('content'));
+  }
+
+  protected function _createActiveRecord($annotation, $content)
+  {
+    $object = new LazyTestOneTableObject();
+    $object->setAnnotation($annotation);
+    $object->setContent($content);
+    $object->save();
+    return $object;
+  }
+}
+?>

Copied: 3.x/trunk/limb/active_record/tests/cases/lmbARAutoTimesTest.class.php (from rev 5951, 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordAutoTimesTest.class.php)
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbARAutoTimesTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbARAutoTimesTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -0,0 +1,86 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+lmb_require('limb/active_record/src/lmbActiveRecord.class.php');
+lmb_require('limb/dbal/src/lmbSimpleDb.class.php');
+
+class TestAutoTimesObject extends lmbActiveRecord
+{
+  protected $_db_table_name = 'test_auto_times_object';
+}
+
+class lmbARAutoTimesTest extends UnitTestCase
+{
+  var $conn;
+  var $db;
+
+  function setUp()
+  {
+    $toolkit = lmbToolkit :: save();
+    $this->conn = $toolkit->getDefaultDbConnection();
+    $this->db = new lmbSimpleDb($this->conn);
+
+    $this->_cleanUp();
+  }
+
+  function tearDown()
+  {
+    $this->_cleanUp();
+
+    lmbToolkit :: restore();
+  }
+
+  function _cleanUp()
+  {
+    $this->db->delete('test_auto_times_object');
+  }
+
+  function testSetTimesAutomaticallyOnCreate()
+  {
+    $time = time();
+    $object = new TestAutoTimesObject();
+    $object->setContent('whatever');
+
+    $id = $object->save();
+
+    $object2 = new TestAutoTimesObject($id);
+    $this->assertTrue($object2->getUpdateTime() >= $time);
+    $this->assertTrue($object2->getCreateTime() >= $time);
+
+    $this->assertEqual($object->getUpdateTime(), $object2->getUpdateTime());
+    $this->assertEqual($object->getCreateTime(), $object2->getCreateTime());
+  }
+
+  function testSetTimesAutomaticallyOnUpdate()
+  {
+    $time = time();
+    $object = new TestAutoTimesObject();
+    $object->setContent('whatever');
+
+    $object->save();
+    $ctime1 =  $object->getCreateTime();
+    $utime1 =  $object->getUpdateTime();
+
+    sleep(1);
+
+    $object->setContent('whatever2');//without this object is considered to be not dirty
+    $object->save();
+    $ctime2 =  $object->getCreateTime();
+    $utime2 =  $object->getUpdateTime();
+
+    $this->assertTrue($ctime1 >= $time);
+    $this->assertTrue($utime1 >= $time);
+    $this->assertEqual($ctime1, $ctime2);
+    $this->assertTrue($utime2 > $utime1);
+
+    $object2 = new TestAutoTimesObject($object->getId());
+    $this->assertEqual($object2->getCreateTime(), $ctime1);
+    $this->assertEqual($object2->getUpdateTime(), $utime2);
+  }
+}
+?>

Copied: 3.x/trunk/limb/active_record/tests/cases/lmbARDirtyTest.class.php (from rev 5951, 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordDirtyTest.class.php)
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbARDirtyTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbARDirtyTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -0,0 +1,249 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+lmb_require('limb/active_record/src/lmbActiveRecord.class.php');
+lmb_require('limb/dbal/src/lmbSimpleDb.class.php');
+lmb_require('limb/dbal/src/lmbTableGateway.class.php');
+require_once(dirname(__FILE__) . '/lmbActiveRecordTest.class.php');
+require_once(dirname(__FILE__) . '/lmbAROneToManyRelationsTest.class.php');
+require_once(dirname(__FILE__) . '/lmbARValueObjectTest.class.php');
+require_once(dirname(__FILE__) . '/lmbAROneToOneRelationsTest.class.php');
+
+class lmbARDirtyTest extends UnitTestCase
+{
+  var $conn = null;
+  var $db = null;
+
+  function setUp()
+  {
+    $toolkit = lmbToolkit :: save();
+    $this->conn = $toolkit->getDefaultDbConnection();
+    $this->db = new lmbSimpleDb($this->conn);
+
+    $this->_cleanUp();
+  }
+
+  function tearDown()
+  {
+    $this->_cleanUp();
+    lmbToolkit :: restore();
+  }
+
+  function _cleanUp()
+  {
+    lmbActiveRecord :: delete('TestOneTableObject');
+    lmbActiveRecord :: delete('LessonForTest');
+    lmbActiveRecord :: delete('CourseForTest');
+    lmbActiveRecord :: delete('LectureForTest');
+  }
+
+  function testJustFoundObjectIsNotDirty()
+  {
+    $object = new TestOneTableObject();
+    $object->setContent('test');
+    $object->save();
+
+    $object2 = lmbActiveRecord :: find('TestOneTableObject', $object->getId());
+    $this->assertFalse($object2->isDirty());
+  }
+
+  function testJustLoadedByIdObjectIsNotDirty()
+  {
+    $object = new TestOneTableObject();
+    $object->setContent('test');
+    $object->save();
+
+    $object2 = new TestOneTableObject($object->getId());
+    $this->assertFalse($object2->isDirty());
+  }
+
+  function testMarkDirty()
+  {
+    $object = new TestOneTableObject();
+    $this->assertFalse($object->isDirty());
+    $object->markDirty();
+    $this->assertTrue($object->isDirty());
+  }
+
+  function testObjectBecomesDirtyIfAttributeIsSetWithSetter()
+  {
+    $object = new TestOneTableObject();
+    $this->assertFalse($object->isDirty());
+    $object->setContent('hey');
+    $this->assertTrue($object->isDirty());
+  }
+
+  function testDirtyObjectBecomesCleanOnceSaved()
+  {
+    $object = new TestOneTableObject();
+    $object->setContent('whatever');
+    $this->assertTrue($object->isDirty());
+    $object->save();
+    $this->assertFalse($object->isDirty());
+  }
+
+  function testNonDirtyObjectIsNotUpdated()
+  {
+    $object = new TestOneTableObjectWithHooks();
+    $object->setContent('whatever');
+
+    ob_start();
+    $object->save();
+    $str = ob_get_contents();
+    ob_end_clean();
+    $this->assertEqual($str, '|on_before_save||on_before_create||on_validate||on_save||on_create||on_after_create||on_after_save|');
+
+    ob_start();
+    $object->save();
+    $str = ob_get_contents();
+    ob_end_clean();
+    $this->assertEqual($str, '|on_before_save||on_after_save|');
+  }
+
+  function testSettingNewParentObjectDoesntMakeNewObjectDirty()
+  {
+    $course = new CourseForTest();
+
+    $lecture = new LectureForTest();
+    $lecture->setCourse($course);
+
+    $this->assertTrue($lecture->isNew());
+    $this->assertFalse($lecture->isDirty());
+  }
+
+  function testParentIsSavedEvenForCleanObject()
+  {
+    $course = new CourseForTest();
+    $course->setTitle('course');
+    $course->save();
+
+    $lecture = new LectureForTest();
+    $lecture->setCourse($course);
+    $lecture->save();
+
+    $lecture2 = new LectureForTest($lecture->getId());
+    $this->assertEqual($lecture2->getCourse()->getTitle(), 'course');
+  }
+
+  function testChangingSavedParentObjectDoesntMakeObjectDirty()
+  {
+    $course = new CourseForTest();
+    $course->setTitle('course');
+    $course->save();
+
+    $lecture = new LectureForTest();
+    $lecture->setCourse($course);
+    $lecture->save();
+
+    $lecture2 = new LectureForTest($lecture->getId());
+    $this->assertFalse($lecture2->isDirty());
+
+    $course2 = $lecture2->getCourse();
+
+    $course2->setTitle('changed_course');
+    $this->assertFalse($lecture2->isDirty());
+  }
+
+  function testSettingExistingParentMakesNewObjectDirty()
+  {
+    $course = new CourseForTest();
+    $course->setTitle('course');
+    $course->save();
+
+    $lecture = new LectureForTest();
+    $lecture->setCourse($course);
+    $this->assertTrue($lecture->isDirty());
+    $lecture->save();
+
+    $lecture2 = new LectureForTest($lecture->getId());
+    $this->assertEqual($lecture2->getCourse()->getTitle(), $course->getTitle());
+  }
+
+  function testSettingExistingParentMakesExistingObjectDirty()
+  {
+    $course = new CourseForTest();
+    $course->setTitle('course');
+    $course->save();
+
+    $lecture = new LectureForTest();
+    $lecture->setTitle('test');
+    $lecture->save();
+
+    $lecture->setCourse($course);
+    $this->assertTrue($lecture->isDirty());
+    $lecture->save();
+
+    $lecture2 = new LectureForTest($lecture->getId());
+    $this->assertEqual($lecture2->getCourse()->getTitle(), $course->getTitle());
+  }
+
+  function testAddingToCollectionDoesntMakeNewObjectDirty()
+  {
+    $course = new CourseForTest();
+
+    $lecture = new LectureForTest();
+
+    $course->addToLectures($lecture);
+    $this->assertFalse($course->isDirty());
+  }
+
+  function testAddingToCollectionDoesntMakeExistingObjectDirty()
+  {
+    $course = new CourseForTest();
+    $course->setTitle('course');
+    $course->save();
+
+    $lecture = new LectureForTest();
+
+    $course->addToLectures($lecture);
+    $this->assertFalse($course->isDirty());
+  }
+
+  function testGettingCollectionDoesntMakeObjectDirty()
+  {
+    $course = new CourseForTest();
+    $lectures = $course->getLectures();
+    $this->assertFalse($course->isDirty());
+  }
+
+  function testSettingValueObjectMakesObjectDirty()
+  {
+    $lesson = new LessonForTest();
+
+    $lesson->setDateStart(new TestingValueObject(time()));
+    $this->assertTrue($lesson->isDirty());
+  }
+
+  function testSettingValueObjectMakesExistingObjectDirty()
+  {
+    $lesson = new LessonForTest();
+    $lesson->setDateStart(new TestingValueObject(time()));
+    $lesson->setDateStart(new TestingValueObject(time() + 30));
+    $lesson->save();
+
+    $lesson2 = new LessonForTest($lesson->getId());
+    $this->assertFalse($lesson->isDirty());
+    $lesson->setDateStart(new TestingValueObject(time() + 10));
+    $this->assertTrue($lesson->isDirty());
+  }
+
+  function testUnsettingOneToOneChildObjectMakesPropertyDirty()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+
+    $person->setSocialSecurity($number);
+    $person->save();
+
+    $person->setSocialSecurity(null);
+    $this->assertTrue($person->isDirtyProperty('social_security'));
+  }
+}
+?>

Copied: 3.x/trunk/limb/active_record/tests/cases/lmbAREventHandlersTest.class.php (from rev 5951, 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordEventHandlersTest.class.php)
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbAREventHandlersTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbAREventHandlersTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -0,0 +1,237 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+require_once(dirname(__FILE__) . '/lmbActiveRecordTest.class.php');
+
+class lmbActiveRecordEventHaldlerStubDelegate
+{
+  var $calls_order = '';
+
+  function onBeforeSave($active_record)
+  {
+    if($active_record instanceof lmbActiveRecord)
+      $this->calls_order .= '|onBeforeSave ' . get_class($active_record) . '|';
+  }
+
+  function onAfterSave($active_record)
+  {
+    if($active_record instanceof lmbActiveRecord)
+      $this->calls_order .= '|onAfterSave ' . get_class($active_record) . '|';
+  }
+
+  function onBeforeUpdate($active_record)
+  {
+    if($active_record instanceof lmbActiveRecord)
+      $this->calls_order .= '|onBeforeUpdate ' . get_class($active_record) . '|';
+  }
+
+  function onUpdate($active_record)
+  {
+    if($active_record instanceof lmbActiveRecord)
+      $this->calls_order .= '|onUpdate ' . get_class($active_record) . '|';
+  }
+
+  function onAfterUpdate($active_record)
+  {
+    if($active_record instanceof lmbActiveRecord)
+      $this->calls_order .= '|onAfterUpdate ' . get_class($active_record) . '|';
+  }
+
+  function onBeforeCreate($active_record)
+  {
+    if($active_record instanceof lmbActiveRecord)
+      $this->calls_order .= '|onBeforeCreate ' . get_class($active_record) . '|';
+  }
+
+  function onCreate($active_record)
+  {
+    if($active_record instanceof lmbActiveRecord)
+      $this->calls_order .= '|onCreate ' . get_class($active_record) . '|';
+  }
+
+  function onAfterCreate($active_record)
+  {
+    if($active_record instanceof lmbActiveRecord)
+      $this->calls_order .= '|onAfterCreate ' . get_class($active_record) . '|';
+  }
+
+  function onBeforeDestroy($active_record)
+  {
+    if($active_record instanceof lmbActiveRecord)
+      $this->calls_order .= '|onBeforeDestroy ' . get_class($active_record) . '|';
+  }
+
+  function onAfterDestroy($active_record)
+  {
+    if($active_record instanceof lmbActiveRecord)
+      $this->calls_order .= '|onAfterDestroy ' . get_class($active_record) . '|';
+  }
+
+  function getCallsOrder()
+  {
+    return $this->calls_order;
+  }
+
+  function subscribeForEvents($active_record)
+  {
+    $active_record->registerOnBeforeSaveCallback($this, 'onBeforeSave');
+    $active_record->registerOnAfterSaveCallback($this, 'onAfterSave');
+    $active_record->registerOnBeforeUpdateCallback($this, 'onBeforeUpdate');
+    $active_record->registerOnUpdateCallback($this, 'onUpdate');
+    $active_record->registerOnAfterUpdateCallback($this, 'onAfterUpdate');
+    $active_record->registerOnBeforeCreateCallback($this, 'onBeforeCreate');
+    $active_record->registerOnCreateCallback($this, 'onCreate');
+    $active_record->registerOnAfterCreateCallback($this, 'onAfterCreate');
+    $active_record->registerOnBeforeDestroyCallback($this, 'onBeforeDestroy');
+    $active_record->registerOnAfterDestroyCallback($this, 'onAfterDestroy');
+  }
+
+  function subscribeGloballyForEvents()
+  {
+    lmbActiveRecord :: registerGlobalOnBeforeSaveCallback($this, 'onBeforeSave');
+    lmbActiveRecord :: registerGlobalOnAfterSaveCallback($this, 'onAfterSave');
+    lmbActiveRecord :: registerGlobalOnBeforeUpdateCallback($this, 'onBeforeUpdate');
+    lmbActiveRecord :: registerGlobalOnUpdateCallback($this, 'onUpdate');
+    lmbActiveRecord :: registerGlobalOnAfterUpdateCallback($this, 'onAfterUpdate');
+    lmbActiveRecord :: registerGlobalOnBeforeCreateCallback($this, 'onBeforeCreate');
+    lmbActiveRecord :: registerGlobalOnCreateCallback($this, 'onCreate');
+    lmbActiveRecord :: registerGlobalOnAfterCreateCallback($this, 'onAfterCreate');
+    lmbActiveRecord :: registerGlobalOnBeforeDestroyCallback($this, 'onBeforeDestroy');
+    lmbActiveRecord :: registerGlobalOnAfterDestroyCallback($this, 'onAfterDestroy');
+  }
+}
+
+class lmbAREventHandlersTest extends UnitTestCase
+{
+  var $conn = null;
+  var $db = null;
+
+  function setUp()
+  {
+    $toolkit = lmbToolkit :: save();
+    $this->conn = $toolkit->getDefaultDbConnection();
+    $this->db = new lmbSimpleDb($this->conn);
+
+    $this->_cleanUp();
+  }
+
+  function tearDown()
+  {
+    $this->_cleanUp();
+
+    lmbToolkit :: restore();
+  }
+
+  function _cleanUp()
+  {
+    $this->db->delete('test_one_table_object');
+  }
+
+  function testSaveNewRecord()
+  {
+    $object = new TestOneTableObject();
+    $object->set('annotation', 'Super annotation');
+    $object->set('content', 'Super content');
+    $object->set('news_date', '2005-01-10');
+
+    $delegate = new lmbActiveRecordEventHaldlerStubDelegate();
+    $delegate->subscribeForEvents($object);
+
+    $object->save();
+
+    $this->assertEqual($delegate->getCallsOrder(),
+                       '|onBeforeSave TestOneTableObject||onBeforeCreate TestOneTableObject||onCreate TestOneTableObject||onAfterCreate TestOneTableObject||onAfterSave TestOneTableObject|');
+  }
+
+  function testUpdateRecord()
+  {
+    $object = new TestOneTableObject();
+    $object->set('annotation', 'Super annotation');
+    $object->set('content', 'Super content');
+    $object->set('news_date', '2005-01-10');
+    $object->save();
+
+    $delegate = new lmbActiveRecordEventHaldlerStubDelegate();
+    $delegate->subscribeForEvents($object);
+
+    $object->set('content', 'New Super content');
+    $object->save();
+
+    $this->assertEqual($delegate->getCallsOrder(),
+                       '|onBeforeSave TestOneTableObject||onBeforeUpdate TestOneTableObject||onUpdate TestOneTableObject||onAfterUpdate TestOneTableObject||onAfterSave TestOneTableObject|');
+  }
+
+  function testDestroyRecord()
+  {
+    $object = new TestOneTableObject();
+    $object->set('annotation', 'Super annotation');
+    $object->set('content', 'Super content');
+    $object->set('news_date', '2005-01-10');
+    $object->save();
+
+    $delegate = new lmbActiveRecordEventHaldlerStubDelegate();
+    $delegate->subscribeForEvents($object);
+
+    $object->destroy();
+
+    $this->assertEqual($delegate->getCallsOrder(),
+                       '|onBeforeDestroy TestOneTableObject||onAfterDestroy TestOneTableObject|');
+  }
+
+  function testSaveNewRecordForGlobalListener()
+  {
+    $object = new TestOneTableObject();
+    $object->set('annotation', 'Super annotation');
+    $object->set('content', 'Super content');
+    $object->set('news_date', '2005-01-10');
+
+    $delegate = new lmbActiveRecordEventHaldlerStubDelegate();
+    $delegate->subscribeGloballyForEvents();
+
+    $object->save();
+
+    $this->assertEqual($delegate->getCallsOrder(),
+                       '|onBeforeSave TestOneTableObject||onBeforeCreate TestOneTableObject||onCreate TestOneTableObject||onAfterCreate TestOneTableObject||onAfterSave TestOneTableObject|');
+  }
+
+  function testUpdateRecordForGlobalListener()
+  {
+    $object = new TestOneTableObject();
+    $object->set('annotation', 'Super annotation');
+    $object->set('content', 'Super content');
+    $object->set('news_date', '2005-01-10');
+    $object->save();
+
+    $delegate = new lmbActiveRecordEventHaldlerStubDelegate();
+    $delegate->subscribeGloballyForEvents($object);
+
+    $object->set('content', 'New Super content');
+    $object->save();
+
+    $this->assertEqual($delegate->getCallsOrder(),
+                       '|onBeforeSave TestOneTableObject||onBeforeUpdate TestOneTableObject||onUpdate TestOneTableObject||onAfterUpdate TestOneTableObject||onAfterSave TestOneTableObject|');
+  }
+
+  function testDestroyRecordForGlobalListener()
+  {
+    $object = new TestOneTableObject();
+    $object->set('annotation', 'Super annotation');
+    $object->set('content', 'Super content');
+    $object->set('news_date', '2005-01-10');
+    $object->save();
+
+    $delegate = new lmbActiveRecordEventHaldlerStubDelegate();
+    $delegate->subscribeGloballyForEvents($object);
+
+    $object->destroy();
+
+    $this->assertEqual($delegate->getCallsOrder(),
+                       '|onBeforeDestroy TestOneTableObject||onAfterDestroy TestOneTableObject|');
+  }
+}
+?>

Copied: 3.x/trunk/limb/active_record/tests/cases/lmbARImportTest.class.php (from rev 5951, 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordImportTest.class.php)
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbARImportTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbARImportTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -0,0 +1,474 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+lmb_require('limb/active_record/src/lmbActiveRecord.class.php');
+lmb_require('limb/dbal/src/lmbSimpleDb.class.php');
+lmb_require('limb/core/src/lmbSet.class.php');
+require_once(dirname(__FILE__) . '/lmbActiveRecordTest.class.php');
+require_once(dirname(__FILE__) . '/lmbAROneToManyRelationsTest.class.php');
+require_once(dirname(__FILE__) . '/lmbAROneToOneRelationsTest.class.php');
+require_once(dirname(__FILE__) . '/lmbARManyToManyRelationsTest.class.php');
+require_once(dirname(__FILE__) . '/lmbARValueObjectTest.class.php');
+require_once(dirname(__FILE__) . '/lmbARAttributesLazyLoadingTest.class.php');
+
+class lmbARImportTest extends UnitTestCase
+{
+  protected $db;
+
+  function setUp()
+  {
+    $this->db = new lmbSimpleDb(lmbToolkit :: instance()->getDefaultDbConnection());
+    $this->_dbCleanUp();
+  }
+
+  function tearDown()
+  {
+    $this->_dbCleanUp();
+  }
+
+  function _dbCleanUp()
+  {
+    lmbActiveRecord :: delete('TestOneTableObject');
+    lmbActiveRecord :: delete('CourseForTest');
+    lmbActiveRecord :: delete('LectureForTest');
+    lmbActiveRecord :: delete('GroupForTest');
+    lmbActiveRecord :: delete('UserForTest');
+    lmbActiveRecord :: delete('LessonForTest');
+    lmbActiveRecord :: delete('PersonForTest');
+    lmbActiveRecord :: delete('SocialSecurityForTest');
+  }
+
+  function testImportingObjectCallsItsExportMethod()
+  {
+    $object = new TestOneTableObject();
+    $object->import(new lmbSet(array('annotation' => 'Some annotation')));
+    $this->assertEqual($object->getAnnotation(), 'Some annotation');
+  }
+
+  function testImportNewActiveRecord()
+  {
+    $object1 = new TestOneTableObject();
+    $object1->setId(100); //note this
+    $object1->setAnnotation($annotation = 'Some annotation');
+
+    $object2 = new TestOneTableObject();
+    $object2->import($object1);
+    $this->assertEqual($object2->getId(), $object1->getId());
+    $this->assertEqual($object2->getAnnotation(), $annotation);
+    $this->assertTrue($object2->isNew());
+    $this->assertTrue($object2->isDirty());
+  }
+
+  function testImportExistingActiveRecord()
+  {
+    $object1 = new TestOneTableObject();
+    $object1->setAnnotation($annotation = 'Some annotation');
+    $object1->save();
+
+    $object2 = new TestOneTableObject();
+    $object2->import($object1);
+    $this->assertEqual($object2->getId(), $object1->getId());
+    $this->assertEqual($object2->getAnnotation(), $annotation);
+    $this->assertFalse($object2->isNew());
+    $this->assertTrue($object2->isDirty());
+  }
+
+  function testPassingActiveRecordToConstructorCallsImport()
+  {
+    $object1 = new TestOneTableObject();
+    $object1->setAnnotation($annotation = 'Some annotation');
+    $object1->save();
+
+    $object2 = new TestOneTableObject($object1);
+    $this->assertEqual($object2->getId(), $object1->getId());
+    $this->assertEqual($object2->getAnnotation(), $annotation);
+    $this->assertFalse($object2->isNew());
+    $this->assertTrue($object2->isDirty());
+  }
+
+  function testImportActiveRecordWithLazyAttributes()
+  {
+    $object = new LazyTestOneTableObject();
+    $object->setContent($content = 'Some content');
+    $object->setAnnotation($annotation = 'Some annotation');
+    $object->save();
+
+    $object1 = new LazyTestOneTableObject();
+    $object2 = new LazyTestOneTableObject($object->getId());
+
+    $object1->import($object2);
+    $this->assertFalse($object1->hasAttribute('annotation'));
+    $this->assertEqual($object1->getAnnotation(), $annotation);
+    $this->assertFalse($object1->hasAttribute('content'));
+    $this->assertEqual($object1->getContent(), $content);
+  }
+
+  function testImportOverwritesIdOfNewObject()
+  {
+    $object = new TestOneTableObject();
+    $object->setId(1);
+
+    $source = array('id' => 1000,
+                    'annotation' => 'Some annotation',
+                    'content' => 'Some content',
+                    );
+
+    $object->import($source);
+    $this->assertEqual($object->getId(), 1000);
+    $this->assertEqual($object->getAnnotation(), 'Some annotation');
+    $this->assertEqual($object->getContent(), 'Some content');
+    $this->assertNull($object->getJunk());
+  }
+
+  function testImportPreservesIdOfExistingObject()
+  {
+    $object = new TestOneTableObject();
+    $object->setAnnotation('Initial annotation');
+    $object->save();
+    $id = $object->getId();
+
+    $source = array('id' => 10000,
+                    'annotation' => 'Some annotation',
+                    'content' => 'Some content',
+                    );
+
+    $object->import($source);
+    $this->assertEqual($object->getId(), $id);
+    $this->assertNotEqual($object->getId(), 1000);// just one extra check
+    $this->assertEqual($object->getAnnotation(), 'Some annotation');
+    $this->assertEqual($object->getContent(), 'Some content');
+  }
+
+  function testPassingArrayToConstructorCallsImport()
+  {
+    $source = array('id' => 1000,
+                    'annotation' => 'Some annotation',
+                    'content' => 'Some content',
+                    );
+
+    $object = new TestOneTableObject($source);
+    $this->assertEqual($object->getId(), 1000);
+    $this->assertEqual($object->getAnnotation(), 'Some annotation');
+    $this->assertEqual($object->getContent(), 'Some content');
+  }
+
+  function testImportWhereOne2ManyCollectionIsArrayOfIds()
+  {
+    $course = new CourseForTest();
+    $course->setTitle('Some course');
+
+    $l1 = new LectureForTest();
+    $l1->setTitle('Physics');
+    $l2 = new LectureForTest();
+    $l2->setTitle('Math');
+
+    $course->addToLectures($l1);
+    $course->addToLectures($l2);
+
+    $course->save();
+
+    $source = array('title' => $course->getTitle(),
+                    'lectures' => array($l1->getId(), $l2->getId()));
+
+    $course2 = new CourseForTest();
+    $course2->import($source);
+    $this->assertEqual($course2->getTitle(), $course->getTitle());
+    $this->assertEqual($course2->getLectures()->count(), 2);
+    $this->assertEqual($course2->getLectures()->at(0)->getTitle(), $l1->getTitle());
+    $this->assertEqual($course2->getLectures()->at(1)->getTitle(), $l2->getTitle());
+  }
+
+  function testImportWhereOne2ManyCollectionIsMixedArray()
+  {
+    $course = new CourseForTest();
+    $course->setTitle('Some course');
+
+    $l1 = new LectureForTest();
+    $l1->setTitle('Physics');
+    $l2 = new LectureForTest();
+    $l2->setTitle('Math');
+
+    $course->addToLectures($l1);
+    $course->addToLectures($l2);
+
+    $course->save();
+
+    $source = array('title' => $course->getTitle(),
+                    'lectures' => array($l1->getId(), $l2));
+
+    $course2 = new CourseForTest();
+    $course2->import($source);
+    $this->assertEqual($course2->getTitle(), $course->getTitle());
+    $this->assertEqual($course2->getLectures()->count(), 2);
+    $this->assertEqual($course2->getLectures()->at(0)->getTitle(), $l1->getTitle());
+    $this->assertEqual($course2->getLectures()->at(1)->getTitle(), $l2->getTitle());
+  }
+
+  function testImportResetsExistingOne2ManyCollection()
+  {
+    $course = new CourseForTest();
+    $course->setTitle('Some course');
+
+    $l1 = new LectureForTest();
+    $l1->setTitle('Physics');
+    $l2 = new LectureForTest();
+    $l2->setTitle('Math');
+
+    $course->addToLectures($l1);
+    $course->addToLectures($l2);
+
+    $course->save();
+
+    $source = array('title' => $course->getTitle(),
+                    'lectures' => array($l2->getId()));
+
+    $course2 = new CourseForTest($course->getId());
+
+    $course2->import($source);
+    $this->assertEqual($course2->getTitle(), $course->getTitle());
+    $this->assertEqual($course2->getLectures()->count(), 1);
+    $this->assertEqual($course2->getLectures()->at(0)->getTitle(), $l2->getTitle());
+  }
+
+  function testImportResetsExistingMany2ManyCollection()
+  {
+    $group = new GroupForTest();
+    $group->setTitle('Some group');
+
+    $u1 = new UserForTest();
+    $u1->setFirstName('Bob');
+    $u2 = new UserForTest();
+    $u2->setFirstName('John');
+
+    $group->addToUsers($u1);
+    $group->addToUsers($u2);
+
+    $group->save();
+
+    $source = array('title' => $group->getTitle(),
+                    'users' => array($u2->getId()));
+
+    $group2 = new GroupForTest($group->getId());
+    $group2->import($source);
+    $this->assertEqual($group2->getTitle(), $group->getTitle());
+    $this->assertEqual($group2->getUsers()->count(), 1);
+    $this->assertEqual($group2->getUsers()->at(0)->getFirstName(), $u2->getFirstName());
+  }
+
+  function testImportWhereOne2ManyParentIsNumericId()
+  {
+    $course = new CourseForTest();
+    $course->setTitle('Some course');
+
+    $l = new LectureForTest();
+    $l->setTitle('Physics');
+    $l->setCourse($course);
+
+    $l->save();
+
+    $source = array('title' => $l->getTitle(),
+                    'course' => $course->getId());
+
+    $l2 = new LectureForTest();
+    $l2->import($source);
+
+    $this->assertEqual($l2->getTitle(), $l->getTitle());
+    $this->assertEqual($l2->getCourse()->getTitle(), $course->getTitle());
+  }
+
+  function testImportWhereOne2ManyParentIsObject()
+  {
+    $course = new CourseForTest();
+    $course->setTitle('Some course');
+
+    $l = new LectureForTest();
+    $l->setTitle('Physics');
+    $l->setCourse($course);
+
+    $l->save();
+
+    $source = array('title' => $l->getTitle(),
+                    'course' => $course);
+
+    $l2 = new LectureForTest();
+    $l2->import($source);
+    $this->assertEqual($l2->getTitle(), $l->getTitle());
+    $this->assertEqual($l2->getCourse()->getTitle(), $course->getTitle());
+  }
+
+  function testImportWhereMany2ManyCollectionIsArrayOfIds()
+  {
+    $user1 = new UserForTest();
+    $user1->setFirstName('Bob');
+
+    $g1 = new GroupForTest();
+    $g1->setTitle('vp1');
+    $g2 = new GroupForTest();
+    $g2->setTitle('vp1');
+
+    $user1->addToGroups($g1);
+    $user1->addToGroups($g2);
+    $user1->save();
+
+    $source = array('first_name' => $user1->getFirstName(),
+                    'groups' => array($g1->getId(), $g2->getId()));
+
+    $user2 = new UserForTest();
+    $user2->import($source);
+    $this->assertEqual($user2->getFirstName(), $user1->getFirstName());
+    $this->assertEqual($user2->getGroups()->count(), 2);
+    $this->assertEqual($user2->getGroups()->at(0)->getTitle(), $g1->getTitle());
+    $this->assertEqual($user2->getGroups()->at(1)->getTitle(), $g2->getTitle());
+  }
+
+  function testImportWhereMany2ManyCollectionIsMixedArray()
+  {
+    $user1 = new UserForTest();
+    $user1->setFirstName('Bob');
+
+    $g1 = new GroupForTest();
+    $g1->setTitle('vp1');
+    $g2 = new GroupForTest();
+    $g2->setTitle('vp1');
+
+    $user1->addToGroups($g1);
+    $user1->addToGroups($g2);
+    $user1->save();
+
+    $source = array('first_name' => $user1->getFirstName(),
+                    'groups' => array($g1->getId(), $g2));
+
+    $user2 = new UserForTest();
+    $user2->import($source);
+    $this->assertEqual($user2->getFirstName(), $user1->getFirstName());
+    $this->assertEqual($user2->getGroups()->count(), 2);
+    $this->assertEqual($user2->getGroups()->at(0)->getTitle(), $g1->getTitle());
+    $this->assertEqual($user2->getGroups()->at(1)->getTitle(), $g2->getTitle());
+  }
+
+  function testImportOne2OneWhereParentIsNumericId()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+    $person->setSocialSecurity($number);
+    $person->save();
+
+    $source = array('code' => $number->getCode(),
+                    'person' => $person->getId());
+
+    $number2 = new SocialSecurityForTest();
+    $number2->import($source);
+    $this->assertEqual($number2->getCode(), $number->getCode());
+    $this->assertEqual($number2->getPerson()->getName(), $person->getName());
+  }
+
+  function testImportOne2OneWhereParentIsObject()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+    $person->setSocialSecurity($number);
+    $person->save();
+
+    $source = array('code' => $number->getCode(),
+                    'person' => $person);
+
+    $number2 = new SocialSecurityForTest();
+    $number2->import($source);
+    $this->assertEqual($number2->getCode(), $number->getCode());
+    $this->assertEqual($number2->getPerson()->getName(), $person->getName());
+  }
+
+  function testImportOne2OneWhereChildIsId()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+    $person->setSocialSecurity($number);
+    $person->save();
+
+    $source = array('name' => $person->getName(),
+                    'social_security' => $number->getId());
+
+    $person2 = new PersonForTest();
+    $person2->import($source);
+    $this->assertEqual($person2->getName(), $person->getName());
+    $this->assertEqual($person2->getSocialSecurity()->getCode(), $number->getCode());
+  }
+
+  function testImportOne2OneWhereChildIsObject()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+    $person->setSocialSecurity($number);
+    $person->save();
+
+    $source = array('name' => $person->getName(),
+                    'social_security' => $number);
+
+    $person2 = new PersonForTest();
+    $person2->import($source);
+    $this->assertEqual($person2->getName(), $person->getName());
+    $this->assertEqual($person2->getSocialSecurity()->getCode(), $number->getCode());
+  }
+
+  function testImportNullEntity()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+    $person->setSocialSecurity($number);
+    $person->save();
+
+    $source = array('name' => $person->getName(),
+                    'social_security' => null);
+
+    $person2 = clone $person;
+    $person2->import($source);
+    $this->assertEqual($person2->getName(), $person->getName());
+    $this->assertNull($person2->getSocialSecurity());
+  }
+
+  function testImportNullEntityString()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+    $person->setSocialSecurity($number);
+    $person->save();
+
+    $source = array('name' => $person->getName(),
+                    'social_security' => 'null');
+
+    $person2 = clone $person;
+    $person2->import($source);
+    $this->assertEqual($person2->getName(), $person->getName());
+    $this->assertNull($person2->getSocialSecurity());
+  }
+
+  function testImportWithValueObject()
+  {
+    $lesson = new LessonForTest();
+
+    $lesson->import(array('date_start' => $v1 = time() - 100,
+                          'date_end' => $v2 = time() + 100));
+
+    $this->assertEqual($lesson->getDateStart()->getValue(), $v1);
+    $this->assertEqual($lesson->getDateEnd()->getValue(), $v2);
+  }
+}
+
+?>

Modified: 3.x/trunk/limb/active_record/tests/cases/lmbARManyToManyCollectionTest.class.php
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbARManyToManyCollectionTest.class.php	2007-06-06 13:55:22 UTC (rev 5951)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbARManyToManyCollectionTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -1,14 +1,14 @@
 <?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com 
- * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
  */
 lmb_require('limb/active_record/src/lmbARManyToManyCollection.class.php');
 lmb_require('limb/dbal/src/lmbSimpleDb.class.php');
-require_once(dirname(__FILE__) . '/lmbActiveRecordManyToManyRelationsTest.class.php');
+require_once(dirname(__FILE__) . '/lmbARManyToManyRelationsTest.class.php');
 
 Mock :: generate('GroupForTest', 'MockGroupForTest');
 

Copied: 3.x/trunk/limb/active_record/tests/cases/lmbARManyToManyRelationsTest.class.php (from rev 5951, 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordManyToManyRelationsTest.class.php)
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbARManyToManyRelationsTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbARManyToManyRelationsTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -0,0 +1,279 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+lmb_require('limb/active_record/src/lmbActiveRecord.class.php');
+lmb_require('limb/dbal/src/lmbSimpleDb.class.php');
+lmb_require('limb/validation/src/rule/lmbRequiredRule.class.php');
+
+class GroupForTest extends lmbActiveRecord
+{
+  protected $_db_table_name = 'group_for_test';
+
+  protected $_has_many_to_many = array('users' => array('field' => 'group_id',
+                                                        'foreign_field' => 'user_id',
+                                                        'table' => 'user2group_for_test',
+                                                        'class' => 'UserForTest'));
+
+  protected $_test_validator;
+
+  function setValidator($validator)
+  {
+    $this->_test_validator = $validator;
+  }
+
+  function _createValidator()
+  {
+    if($this->_test_validator)
+      return $this->_test_validator;
+
+    return parent :: _createValidator();
+  }
+}
+
+class UserForTest extends lmbActiveRecord
+{
+  protected $_db_table_name = 'user_for_test';
+
+  protected $_has_many_to_many = array('groups' => array('field' => 'user_id',
+                                                         'foreign_field' => 'group_id',
+                                                         'table' => 'user2group_for_test',
+                                                         'class' => 'GroupForTest'));
+}
+
+class GroupsForTestCollectionStub extends lmbARManyToManyCollection{}
+
+class UserForTestWithCustomCollection extends lmbActiveRecord
+{
+  protected $_db_table_name = 'user_for_test';
+
+  protected $_has_many_to_many = array('groups' => array('field' => 'user_id',
+                                                         'foreign_field' => 'group_id',
+                                                         'table' => 'user2group_for_test',
+                                                         'class' => 'GroupForTest',
+                                                         'collection' => 'GroupsForTestCollectionStub'));
+}
+
+class lmbARManyToManyRelationsTest extends UnitTestCase
+{
+  protected $db;
+
+  function setUp()
+  {
+    $this->db = new lmbSimpleDb(lmbToolkit :: instance()->getDefaultDbConnection());
+    $this->_dbCleanUp();
+  }
+
+  function tearDown()
+  {
+    $this->_dbCleanUp();
+  }
+
+  function _dbCleanUp()
+  {
+    lmbActiveRecord :: delete('GroupForTest');
+    lmbActiveRecord :: delete('UserForTest');
+  }
+
+  function testMapPropertyToField()
+  {
+    $group = new GroupForTest();
+    $this->assertEqual('users', $group->mapFieldToProperty('group_id'));
+    $this->assertNull($group->mapFieldToProperty('blah'));
+  }
+
+  function testNewObjectReturnsEmptyCollection()
+  {
+    $user = new UserForTest();
+    $groups = $user->getGroups();
+    $groups->rewind();
+    $this->assertFalse($groups->valid());
+  }
+
+  function testAddFromOneSideOfRelation()
+  {
+    $user = new UserForTest();
+    $user->setFirstName('Bob');
+
+    $group1 = new GroupForTest();
+    $group1->setTitle('vp1');
+
+    $group2 = new GroupForTest();
+    $group2->setTitle('vp2');
+
+    $user->addToGroups($group1);
+    $user->addToGroups($group2);
+    $user->save();
+
+    $user2 = lmbActiveRecord :: findById('UserForTest', $user->getId());
+    $rs = $user2->getGroups();
+
+    $rs->rewind();
+    $this->assertTrue($rs->valid());
+    $this->assertEqual($rs->current()->getTitle(), $group1->getTitle());
+    $this->assertEqual($rs->current()->getId(), $group1->getId());
+    $rs->next();
+    $this->assertEqual($rs->current()->getTitle(), $group2->getTitle());
+    $this->assertEqual($rs->current()->getId(), $group2->getId());
+  }
+
+  function testLoadShouldNotMixTables()
+  {
+    $user1 = new UserForTest();
+    $user1->setFirstName('Bob');
+
+    $user2 = new UserForTest();
+    $user2->setFirstName('Joe');
+
+    $group1 = new GroupForTest();
+    $group1->setTitle('vp1');
+
+    $group2 = new GroupForTest();
+    $group2->setTitle('vp2');
+
+    $user1->addToGroups($group1);
+    $user1->addToGroups($group2);
+    $user1->save();
+
+    $user2->addToGroups($group1);
+    $user2->addToGroups($group2);
+    $user2->save();
+
+    $user3 = lmbActiveRecord :: findById('UserForTest', $user2->getId());
+    $rs = $user3->getGroups();
+
+    $rs->rewind();
+    $this->assertTrue($rs->valid());
+    $this->assertEqual($rs->current()->getTitle(), $group1->getTitle());
+    $this->assertEqual($rs->current()->getId(), $group1->getId());
+    $rs->next();
+    $this->assertEqual($rs->current()->getTitle(), $group2->getTitle());
+    $this->assertEqual($rs->current()->getId(), $group2->getId());
+  }
+
+  function testSetingCollectionDirectlyCallsAddToMethod()
+  {
+    $user = new UserForTest();
+    $user->setFirstName('Bob');
+
+    $g1 = new GroupForTest();
+    $g1->setTitle('vp1');
+    $g2 = new GroupForTest();
+    $g2->setTitle('vp2');
+
+    $user->setGroups(array($g1, $g2));
+    $arr = $user->getGroups()->getArray();
+    $this->assertEqual(sizeof($arr), 2);
+    $this->assertEqual($arr[0]->getTitle(), $g1->getTitle());
+    $this->assertEqual($arr[1]->getTitle(), $g2->getTitle());
+  }
+
+  function testSetFlushesPreviousCollection()
+  {
+    $user = new UserForTest();
+    $user->setFirstName('Bob');
+
+    $g1 = new GroupForTest();
+    $g1->setTitle('vp1');
+    $g2 = new GroupForTest();
+    $g2->setTitle('vp2');
+
+    $user->addToGroups($g1);
+    $user->addToGroups($g2);
+
+    $user->setGroups(array($g1));
+    $groups = $user->getGroups()->getArray();
+    $this->assertEqual($groups[0]->getTitle(), $g1->getTitle());
+    $this->assertEqual(sizeof($groups), 1);
+  }
+
+  function testUpdateRelations()
+  {
+    $user = new UserForTest();
+    $user->setFirstName('Bob');
+
+    $group1 = new GroupForTest();
+    $group1->setTitle('vp1');
+
+    $group2 = new GroupForTest();
+    $group2->setTitle('vp2');
+
+    $user->addToGroups($group1);
+    $user->addToGroups($group2);
+    $user->save();
+
+    $user2 = lmbActiveRecord :: findById('UserForTest', $user->getId());
+    $user2->setGroups(array($group2));
+    $user2->save();
+
+    $user3 = lmbActiveRecord :: findById('UserForTest', $user->getId());
+    $groups = $user3->getGroups();
+
+    $this->assertEqual($groups->at(0)->getTitle(), $group2->getTitle());
+    $this->assertEqual($groups->count(), 1);
+  }
+
+  function testDeleteAlsoRemovesManyToManyRecords()
+  {
+    $user1 = new UserForTest();
+    $user1->setFirstName('Bob');
+
+    $user2 = new UserForTest();
+    $user2->setFirstName('Bob');
+
+    $group1 = new GroupForTest();
+    $group1->setTitle('vp1');
+
+    $group2 = new GroupForTest();
+    $group2->setTitle('vp2');
+
+    $user1->addToGroups($group1);
+    $user1->addToGroups($group2);
+    $user1->save();
+
+    $user2->addToGroups($group1);
+    $user2->addToGroups($group2);
+    $user2->save();
+
+    $user3 = lmbActiveRecord :: findById('UserForTest', $user1->getId());
+    $user3->destroy();
+
+    $this->assertEqual($this->db->count('user2group_for_test'), 2);
+
+    $user4 = lmbActiveRecord :: findById('UserForTest', $user2->getId());
+    $groups = $user4->getGroups();
+    $this->assertEqual($groups->at(0)->getTitle(), $group1->getTitle());
+    $this->assertEqual($groups->at(1)->getTitle(), $group2->getTitle());
+    $this->assertEqual($groups->count(), 2);
+  }
+
+  function testUseCustomCollection()
+  {
+    $user = new UserForTestWithCustomCollection();
+    $this->assertTrue($user->getGroups() instanceof GroupsForTestCollectionStub);
+  }
+
+  function testErrorListIsSharedWithCollection()
+  {
+    $user = new UserForTest();
+    $user->setFirstName('Bob');
+
+    $group = new GroupForTest();
+
+    $validator = new lmbValidator();
+    $validator->addRequiredRule('title');
+    $group->setValidator($validator);
+
+    $user->addToGroups($group);
+    $user->addToGroups($group);
+
+    $error_list = new lmbErrorList();
+    $this->assertFalse($user->trySave($error_list));
+  }
+}
+
+?>

Modified: 3.x/trunk/limb/active_record/tests/cases/lmbAROneToManyCollectionTest.class.php
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbAROneToManyCollectionTest.class.php	2007-06-06 13:55:22 UTC (rev 5951)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbAROneToManyCollectionTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -1,15 +1,15 @@
 <?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com 
- * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
  */
 lmb_require('limb/active_record/src/lmbAROneToManyCollection.class.php');
 lmb_require('limb/core/src/lmbCollectionDecorator.class.php');
 lmb_require('limb/dbal/src/lmbSimpleDb.class.php');
-require_once(dirname(__FILE__) . '/lmbActiveRecordOneToManyRelationsTest.class.php');
+require_once(dirname(__FILE__) . '/lmbAROneToManyRelationsTest.class.php');
 
 Mock :: generate('LectureForTest', 'MockLectureForTest');
 

Copied: 3.x/trunk/limb/active_record/tests/cases/lmbAROneToManyRelationsTest.class.php (from rev 5951, 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordOneToManyRelationsTest.class.php)
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbAROneToManyRelationsTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbAROneToManyRelationsTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -0,0 +1,443 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+lmb_require('limb/active_record/src/lmbActiveRecord.class.php');
+lmb_require('limb/active_record/src/lmbAROneToManyCollection.class.php');
+lmb_require('limb/dbal/src/lmbSimpleDb.class.php');
+
+class CourseForTest extends lmbActiveRecord
+{
+  protected $_db_table_name = 'course_for_test';
+  protected $_has_many = array('lectures' => array('field' => 'course_id',
+                                                   'class' => 'LectureForTest'),
+                               'alt_lectures' => array('field' => 'alt_course_id',
+                                                       'class' => 'LectureForTest'));
+
+  public $save_calls = 0;
+
+  function save()
+  {
+    parent :: save();
+    $this->save_calls++;
+  }
+}
+
+class LectureForTest extends lmbActiveRecord
+{
+  protected $_db_table_name = 'lecture_for_test';
+  protected $_many_belongs_to = array('course' => array('field' => 'course_id',
+                                                        'class' => 'CourseForTest'),
+                                      'alt_course' => array('field' => 'alt_course_id',
+                                                            'class' => 'CourseForTest',
+                                                            'can_be_null' => true));
+  protected $_test_validator;
+
+  function setValidator($validator)
+  {
+    $this->_test_validator = $validator;
+  }
+
+  function _createValidator()
+  {
+    if($this->_test_validator)
+      return $this->_test_validator;
+
+    return parent :: _createValidator();
+  }
+}
+
+class LecturesForTestCollectionStub extends lmbAROneToManyCollection{}
+
+class CourseForTestWithCustomCollection extends lmbActiveRecord
+{
+  protected $_db_table_name = 'course_for_test';
+  protected $_has_many = array('lectures' => array('field' => 'course_id',
+                                                   'class' => 'LectureForTest',
+                                                   'collection' => 'LecturesForTestCollectionStub'));
+}
+
+class CourseForTestWithNullifyRelationProperty extends lmbActiveRecord
+{
+  protected $_db_table_name = 'course_for_test';
+  protected $_has_many = array('lectures' => array('field' => 'course_id',
+                                                   'class' => 'LectureForTest',
+                                                   'nullify' => true));
+}
+
+Mock :: generate('LectureForTest', 'MockLectureForTest');
+
+class lmbAROneToManyRelationsTest extends UnitTestCase
+{
+  protected $db;
+
+  function setUp()
+  {
+    $this->db = new lmbSimpleDb(lmbToolkit :: instance()->getDefaultDbConnection());
+    $this->_dbCleanUp();
+  }
+
+  function tearDown()
+  {
+    $this->_dbCleanUp();
+  }
+
+  function _dbCleanUp()
+  {
+    $this->db->delete('course_for_test');
+    $this->db->delete('lecture_for_test');
+  }
+
+  function testMapPropertyToField()
+  {
+    $course = new CourseForTest();
+    $this->assertEqual('lectures', $course->mapFieldToProperty('course_id'));
+    $this->assertNull($course->mapFieldToProperty('blah'));
+
+    $lecture = new LectureForTest();
+    $this->assertEqual('course', $lecture->mapFieldToProperty('course_id'));
+    $this->assertNull($lecture->mapFieldToProperty('blah'));
+  }
+
+  function testNewObjectReturnsEmptyCollection()
+  {
+    $course = new CourseForTest();
+    $lectures = $course->getLectures();
+    $lectures->rewind();
+    $this->assertFalse($lectures->valid());
+  }
+
+  function testNewObjectReturnsNullParent()
+  {
+    $lecture = new LectureForTest();
+    $this->assertNull($lecture->getCourse());
+  }
+
+  function testAddToCollection()
+  {
+    $course = $this->_initCourse();
+
+    $l1 = new LectureForTest();
+    $l1->setTitle('Physics');
+    $l2 = new LectureForTest();
+    $l2->setTitle('Math');
+
+    $course->addToLectures($l1);
+    $course->addToLectures($l2);
+
+    $rs = $course->getLectures();
+
+    $rs->rewind();
+    $this->assertEqual($rs->current()->getTitle(), $l1->getTitle());
+    $rs->next();
+    $this->assertEqual($rs->current()->getTitle(), $l2->getTitle());
+  }
+
+  function testSetingCollectionDirectlyCallsAddToMethod()
+  {
+    $course = $this->_initCourse();
+
+    $l1 = new LectureForTest();
+    $l1->setTitle('Physics');
+    $l2 = new LectureForTest();
+    $l2->setTitle('Math');
+
+    $course->setLectures(array($l1, $l2));
+    $lectures = $course->getLectures();
+    $this->assertEqual(sizeof($lectures), 2);
+    $this->assertEqual($lectures[0]->getTitle(), $l1->getTitle());
+    $this->assertEqual($lectures[1]->getTitle(), $l2->getTitle());
+  }
+
+  function testSetFlushesPreviousCollection()
+  {
+    $course = $this->_initCourse();
+
+    $l1 = new LectureForTest();
+    $l1->setTitle('Physics');
+    $l2 = new LectureForTest();
+    $l2->setTitle('Math');
+
+    $course->addToLectures($l1);
+    $course->addToLectures($l2);
+
+    $course->setLectures(array($l1));
+    $lectures = $course->getLectures()->getArray();
+    $this->assertEqual($lectures[0]->getTitle(), $l1->getTitle());
+    $this->assertEqual(sizeof($lectures), 1);
+  }
+
+  function testSaveCollection()
+  {
+    $course = $this->_initCourse();
+
+    $l1 = new LectureForTest();
+    $l1->setTitle('Physics');
+    $l2 = new LectureForTest();
+    $l2->setTitle('Math');
+
+    $course->addToLectures($l1);
+    $course->addToLectures($l2);
+
+    $course->save();
+
+    $course2 = lmbActiveRecord :: findById('CourseForTest', $course->getId());
+    $rs = $course2->getLectures();
+
+    $rs->rewind();
+    $this->assertEqual($rs->current()->getTitle(), $l1->getTitle());
+    $rs->next();
+    $this->assertEqual($rs->current()->getTitle(), $l2->getTitle());
+  }
+
+  function testGenericGetLoadsCollection()
+  {
+    $course = $this->_initCourse();
+
+    $l1 = new LectureForTest();
+    $l1->setTitle('Physics');
+    $l2 = new LectureForTest();
+    $l2->setTitle('Math');
+
+    $course->addToLectures($l1);
+    $course->addToLectures($l2);
+
+    $course->save();
+
+    $course2 = lmbActiveRecord :: findById('CourseForTest', $course->getId());
+    $rs = $course2->get('lectures');
+
+    $rs->rewind();
+    $this->assertEqual($rs->current()->getTitle(), $l1->getTitle());
+    $rs->next();
+    $this->assertEqual($rs->current()->getTitle(), $l2->getTitle());
+  }
+
+  function testParentObjectCanBeNull()
+  {
+    $course = $this->_initCourse();
+
+    $lecture = new LectureForTest();
+    $lecture->setTitle('Physics');
+    $lecture->setCourse($course);
+    $lecture->save();
+
+    $lecture2 = lmbActiveRecord :: findById('LectureForTest', $lecture->getId());
+    $this->assertEqual($lecture2->getCourse()->getTitle(), $course->getTitle());
+    $this->assertNull($lecture2->getAltCourse());
+
+    $lecture2->setAltCourse($course);
+    $lecture2->save();
+
+    $lecture3 = lmbActiveRecord :: findById('LectureForTest', $lecture2->getId());
+    $this->assertEqual($lecture3->getCourse()->getTitle(), $course->getTitle());
+    $this->assertEqual($lecture3->getAltCourse()->getTitle(), $course->getTitle());
+  }
+
+  function testSettingNullParentObject()
+  {
+    $course = $this->_initCourse();
+
+    $lecture = new LectureForTest();
+    $lecture->setTitle('Physics');
+    $lecture->setAltCourse($course);
+    $lecture->save();
+
+    $this->assertEqual($course->getAltLectures()->count(), 1);
+
+    $lecture2 = lmbActiveRecord :: findById('LectureForTest', $lecture->getId());
+
+    $lecture2->setAltCourse(null);
+    $lecture2->save();
+
+    $this->assertEqual($course->getAltLectures()->count(), 0);
+
+    $lecture3 = lmbActiveRecord :: findById('LectureForTest', $lecture2->getId());
+    $this->assertNull($lecture3->getAltCourse());
+  }
+
+  function testSavingChildForExistingParentDoesntSaveParent()
+  {
+    $course = $this->_initCourse();
+
+    $this->assertEqual($course->save_calls, 0);
+
+    $course->save();
+
+    $this->assertEqual($course->save_calls, 1);
+
+    $lecture = new LectureForTest();
+    $lecture->setTitle('Physics');
+    $lecture->setAltCourse($course);
+    $lecture->save();
+
+    $this->assertEqual($course->save_calls, 1);
+  }
+
+  function testChangingParentIdRelationFieldDirectly()
+  {
+    $course1 = $this->_initCourse();
+    $course1->save();
+
+    $course2 = $this->_initCourse();
+    $course2->save();
+
+    $lecture = new LectureForTest();
+    $lecture->setTitle('Physics');
+    $lecture->setCourse($course1);
+    $lecture->save();
+
+    $lecture2 = new LectureForTest($lecture->getId());
+    $this->assertEqual($lecture2->getCourse()->getId(), $course1->getId());
+
+    $lecture2->set('course_id', $course2->getId());
+    $lecture2->save();
+
+    $lecture3 = new LectureForTest($lecture->getId());
+    $this->assertEqual($lecture3->getCourse()->getId(), $course2->getId());
+  }
+
+  function testChangingParentIdRelationFieldDirectlyDoesNotWorkIfParentObjectIsDirty()
+  {
+    $course1 = $this->_initCourse();
+    $course1->save();
+
+    $course2 = $this->_initCourse();
+    $course2->save();
+
+    $lecture = new LectureForTest();
+    $lecture->setTitle('Physics');
+    $lecture->setCourse($course1);
+    $lecture->save();
+
+    $lecture2 = new LectureForTest($lecture->getId());
+    $this->assertEqual($lecture2->getCourse()->getId(), $course1->getId());
+
+    $lecture2->set('course_id', $course2->getId());
+    $lecture2->setCourse($course1);
+    $lecture2->save();
+
+    $lecture3 = new LectureForTest($lecture->getId());
+    $this->assertEqual($lecture3->getCourse()->getId(), $course1->getId());
+  }
+
+  function testOwnerSetAutomaticallyForChildAddedToCollection()
+  {
+    $course = $this->_initCourse();
+
+    $lecture = new LectureForTest();
+    $lecture->setTitle('Physics');
+
+    $course->getLectures()->add($lecture);
+
+    $this->assertReference($lecture->getCourse(), $course);
+  }
+
+  function testDeleteCollection()
+  {
+    $course = $this->_initCourse();
+
+    $l1 = new LectureForTest();
+    $l1->setTitle('Physics');
+    $l2 = new LectureForTest();
+    $l2->setTitle('Math');
+
+    $course->addToLectures($l1);
+    $course->addToLectures($l2);
+
+    $course->save();
+
+    $course2 = lmbActiveRecord :: findById('CourseForTest', $course->getId());
+    $course2->destroy();
+
+    $this->assertNull(lmbActiveRecord :: findFirst('LectureForTest', array('criteria' => 'id = ' . $l1->getId())));
+    $this->assertNull(lmbActiveRecord :: findFirst('LectureForTest', array('criteria' => 'id = ' . $l2->getId())));
+  }
+
+  function testNullifyOnDestroy()
+  {
+    $course = new CourseForTestWithNullifyRelationProperty();
+    $course->setTitle('Super course');
+
+    $l1 = new LectureForTest();
+    $l1->setTitle('Physics');
+    $l2 = new LectureForTest();
+    $l2->setTitle('Math');
+
+    $course->addToLectures($l1);
+    $course->addToLectures($l2);
+
+    $course->save();
+
+    $course2 = new CourseForTestWithNullifyRelationProperty($course->getId());
+    $course2->destroy();
+
+    $lectures = lmbActiveRecord :: find('LectureForTest')->getArray();
+    $this->assertEqual(sizeof($lectures), 2);
+    $this->assertNull($lectures[0]->getCourseId());
+    $this->assertNull($lectures[0]->getCourseId());
+  }
+
+  function testUseCustomCollection()
+  {
+    $course = new CourseForTestWithCustomCollection();
+    $this->assertTrue($course->getLectures() instanceof LecturesForTestCollectionStub);
+  }
+
+  function testSetFlushesPreviousCollectionInDatabaseToo()
+  {
+    $course = $this->_initCourse();
+
+    $l1 = new LectureForTest();
+    $l1->setTitle('Physics');
+    $l2 = new LectureForTest();
+    $l2->setTitle('Math');
+
+    $course->addToLectures($l1);
+    $course->addToLectures($l2);
+
+    $course->save();
+
+    $course2 = lmbActiveRecord :: findById('CourseForTest', $course->getId());
+
+    $l3 = new LectureForTest();
+    $l3->setTitle('Math');
+
+    $course2->setLectures(array($l3));
+    $course2->save();
+
+    $course3 = lmbActiveRecord :: findById('CourseForTest', $course->getId());
+
+    $lectures = $course3->getLectures();
+    $this->assertEqual($lectures->count(), 1);
+    $this->assertEqual($lectures->at(0)->getTitle(), $l3->getTitle());
+  }
+
+  function testErrorListIsSharedWithCollection()
+  {
+    $course = $this->_initCourse();
+
+    $l = new LectureForTest();
+    $validator = new lmbValidator();
+    $validator->addRequiredRule('title');
+    $l->setValidator($validator);
+
+    $course->addToLectures($l);
+
+    $error_list = new lmbErrorList();
+    $this->assertFalse($course->trySave($error_list));
+  }
+
+  function _initCourse()
+  {
+    $course = new CourseForTest();
+    $course->setTitle('Course'. mt_rand());
+    return $course;
+  }
+}
+
+?>

Copied: 3.x/trunk/limb/active_record/tests/cases/lmbAROneToOneRelationsTest.class.php (from rev 5951, 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordOneToOneRelationsTest.class.php)
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbAROneToOneRelationsTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbAROneToOneRelationsTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -0,0 +1,434 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+lmb_require('limb/active_record/src/lmbActiveRecord.class.php');
+lmb_require('limb/dbal/src/lmbSimpleDb.class.php');
+
+class PersonForTest extends lmbActiveRecord
+{
+  public $save_count = 0;
+  protected $_has_one = array('social_security' => array('field' => 'ss_id',
+                                                         'class' => 'SocialSecurityForTest',
+                                                         'can_be_null' => true));
+
+  function _onSave()
+  {
+    $this->save_count++;
+  }
+
+}
+
+class PersonForTestNoCascadeDelete extends lmbActiveRecord
+{
+  protected $_db_table_name = 'person_for_test';
+  protected $_has_one = array('social_security' => array('field' => 'ss_id',
+                                                         'class' => 'SocialSecurityForTest',
+                                                         'can_be_null' => true,
+                                                         'cascade_delete' => false));
+}
+
+class PersonForTestWithRequiredSocialSecurity extends lmbActiveRecord
+{
+  protected $_db_table_name = 'person_for_test';
+  protected $_has_one = array('social_security' => array('field' => 'ss_id',
+                                                         'class' => 'SocialSecurityForTest',
+                                                         'can_be_null' => true));
+
+  function _createValidator()
+  {
+    $validator = new lmbValidator();
+    $validator->addRequiredObjectRule('social_security');
+    return $validator;
+  }
+}
+
+class SocialSecurityForTest extends lmbActiveRecord
+{
+  protected $_belongs_to = array('person' => array('field' => 'ss_id',
+                                                   'class' => 'PersonForTest'));
+}
+
+class lmbAROneToOneRelationsTest extends UnitTestCase
+{
+  protected $db;
+
+  function setUp()
+  {
+    $this->db = new lmbSimpleDb(lmbToolkit :: instance()->getDefaultDbConnection());
+    $this->_dbCleanUp();
+  }
+
+  function tearDown()
+  {
+    $this->_dbCleanUp();
+  }
+
+  function _dbCleanUp()
+  {
+    $this->db->delete('person_for_test');
+    $this->db->delete('social_security_for_test');
+  }
+
+  function testNewObjectReturnsNullChild()
+  {
+    $person = new PersonForTest();
+    $this->assertNull($person->getSocialSecurity());
+  }
+
+  function testNewObjectReturnsNullParent()
+  {
+    $number = new SocialSecurityForTest();
+    $this->assertNull($number->getPerson());
+  }
+
+  function testSaveChild()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+
+    $person->setSocialSecurity($number);
+
+    $this->assertNull($number->getId());
+
+    $person->save();
+
+    $this->assertNotNull($number->getId());
+  }
+
+  function testSaveParent()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+
+    $number->setPerson($person);
+
+    $this->assertNull($person->getId());
+
+    $number->save();
+
+    $this->assertNotNull($person->getId());
+  }
+
+  function testDontSaveParentSecondTimeIfChildWasChanged()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+
+    $person->setSocialSecurity($number);
+    $person->save();
+
+    $this->assertEqual($person->save_count, 1);
+
+    $person->save();
+
+    $this->assertEqual($person->save_count, 1);
+  }
+
+  function testSavingParentSavesChildAsWell()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+
+    $person->setSocialSecurity($number);
+    $person->save();
+
+    $number->setCode($new_code = '0022112');
+    $person->save();
+
+    $loaded_number = new SocialSecurityForTest($number->getId());
+    $this->assertEqual($loaded_number->getCode(), $new_code);
+  }
+
+  function testChangingChildObjectIdDirectly()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+
+    $number1 = new SocialSecurityForTest();
+    $number1->setCode('099123');
+
+    $person->setSocialSecurity($number1);
+    $person->save();
+
+    $number2 = new SocialSecurityForTest();
+    $number2->setCode('143453');
+    $number2->save();
+
+    $person2 = new PersonForTest($person->getId());
+    $this->assertEqual($person2->getSocialSecurity()->getId(), $number1->getId());
+
+    $person2->set('ss_id', $number2->getId());
+    $person2->save();
+
+    $person3 = new PersonForTest($person->getId());
+    $this->assertEqual($person3->getSocialSecurity()->getId(), $number2->getId());
+  }
+
+  function testChangingChildIdRelationFieldDirectlyHasNoAffectIfChildObjectPropertyIsDirty()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+
+    $number1 = new SocialSecurityForTest();
+    $number1->setCode('099123');
+
+    $person->setSocialSecurity($number1);
+    $person->save();
+
+    $number2 = new SocialSecurityForTest();
+    $number2->setCode('143453');
+    $number2->save();
+
+    $person2 = new PersonForTest($person->getId());
+    $this->assertEqual($person2->getSocialSecurity()->getId(), $number1->getId());
+
+    $person2->set('ss_id', $number2->getId()); // changing child relation field directly
+    $person2->setSocialSecurity($number1); // and making child object dirty
+    $person2->save();
+
+    $person3 = new PersonForTest($person->getId());
+    $this->assertEqual($person3->getSocialSecurity()->getId(), $number1->getId());
+  }
+
+  function testLoadParentObject()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+
+    $person->setSocialSecurity($number);
+
+    $person->save();
+
+    $number2 = lmbActiveRecord :: findById('SocialSecurityForTest', $number->getId());
+
+    $person2 = $number2->getPerson();
+
+    $this->assertEqual($person2->getId(), $person->getId());
+    $this->assertEqual($person2->getName(), 'Jim');
+  }
+
+  function testGenericGetLoadsChildObject()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+
+    $person->setSocialSecurity($number);
+
+    $person->save();
+
+    $number2 = lmbActiveRecord :: findById('SocialSecurityForTest', $number->getId());
+
+    $person2 = $number2->getPerson();
+
+    $this->assertEqual($person2->getId(), $person->getId());
+    $this->assertEqual($person2->getName(), 'Jim');
+  }
+
+  function testLoadChildObject()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+
+    $person->setSocialSecurity($number);
+
+    $person_id = $person->save();
+
+    $person2 = lmbActiveRecord :: findById('PersonForTest', $person_id);
+    $number2 = $person2->getSocialSecurity();
+
+    $this->assertEqual($person2->getId(), $person_id);
+    $this->assertEqual($person2->getName(), 'Jim');
+    $this->assertEqual($number2->getId(), $number->getId());
+    $this->assertEqual($number2->getCode(), '099123');
+  }
+
+  function testGenericGetLoadsParentObject()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+
+    $person->setSocialSecurity($number);
+
+    $person_id = $person->save();
+
+    $person2 = lmbActiveRecord :: findById('PersonForTest', $person_id);
+    $number2 = $person2->get('social_security');
+
+    $this->assertEqual($person2->getId(), $person_id);
+    $this->assertEqual($person2->getName(), 'Jim');
+    $this->assertEqual($number2->getId(), $number->getId());
+    $this->assertEqual($number2->getCode(), '099123');
+  }
+
+  function testParentRemovalDeletesChildren()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+
+    $person->setSocialSecurity($number);
+
+    $person_id = $person->save();
+    $this->assertTrue($number_id = $number->getId());
+
+    $person->destroy();
+
+    $this->assertNull(lmbActiveRecord :: findFirst('SocialSecurityForTest', array('criteria' => 'id = ' . $number_id)));
+    $this->assertNull(lmbActiveRecord :: findFirst('PersonForTest', array('criteria' => 'id = ' . $person_id)));
+  }
+
+  function testParentDeleteAllDeletesChildren()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+
+    $person->setSocialSecurity($number);
+
+    $person_id = $person->save();
+    $number_id = $number->getId();
+
+    //this one should stay
+    $untouched_number = new SocialSecurityForTest();
+    $untouched_number->setCode('0893127');
+    $untouched_number->save();
+
+    lmbActiveRecord :: delete('PersonForTest');
+
+    $this->assertNull(lmbActiveRecord :: findFirst('SocialSecurityForTest', array('criteria' => 'id = ' . $number_id)));
+    $this->assertNull(lmbActiveRecord :: findFirst('PersonForTest', array('criteria' => 'id = ' . $person_id)));
+
+    $number2 = lmbActiveRecord :: findById('SocialSecurityForTest', $untouched_number->getId());
+    $this->assertEqual($number2->getCode(), '0893127');
+  }
+
+  function testParentRemovalWithNoCascadeDeleteChildren()
+  {
+    $person = new PersonForTestNoCascadeDelete();
+    $person->setName('Jim');
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+
+    $person->setSocialSecurity($number);
+
+    $person_id = $person->save();
+    $this->assertTrue($number_id = $number->getId());
+
+    $person->destroy();
+
+    $ss2 = lmbActiveRecord :: findFirst('SocialSecurityForTest', array('criteria' => 'id = ' . $number_id));
+    $this->assertEqual($ss2->getCode(), $number->getCode());
+  }
+
+  function testChildRemovalNullifyParentField()
+  {
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+
+    $person = new PersonForTest();
+    $person->setName('Jim');
+
+    $person->setSocialSecurity($number);
+    $number->setPerson($person);
+    $person->setNumber($number);
+    $person->save();
+
+    $number->destroy();
+
+    $person2 = new PersonForTest($person->getId());
+    $this->assertNull($person2->get('ss_id'));
+  }
+
+  function testChildRemovalWithRequiredObjectInParentRelationDefinitionThrowsValidationException()
+  {
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+
+    $person = new PersonForTestWithRequiredSocialSecurity();
+    $person->setName('Jim');
+
+    $person->setSocialSecurity($number);
+    $number->setPerson($person);
+    $person->save();
+
+    try
+    {
+      $number->destroy();
+      $this->assertTrue(false);
+    }
+    catch(lmbValidationException $e)
+    {
+      $this->assertTrue(true);
+    }
+
+    $number2 = lmbActiveRecord :: findFirst('SocialSecurityForTest');
+    $this->assertNotNull($number2, 'Removal should not be finished');
+    $this->assertEqual($number2->getId(), $number->getId());
+  }
+
+  function testSettingNullDetachesChildObject()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+
+    $person->setSocialSecurity($number);
+    $person->save();
+
+    $person->setSocialSecurity(null);
+    $person_id = $person->save();
+
+    $person2 = new PersonForTest($person_id);
+    $this->assertNull($person2->getSocialSecurity());
+
+    $number2 = new SocialSecurityForTest($number->getId());
+    $this->assertEqual($number2->getCode(), $number->getCode());
+  }
+
+  function testDontResetParentIfChildImport()
+  {
+    $person = new PersonForTest();
+    $person->setName('Jim');
+    $number = new SocialSecurityForTest();
+    $number->setCode('099123');
+    $person->setSocialSecurity($number);
+    $person->save();
+
+    $source = array('name' => $person->getName());
+
+    $person2 = new PersonForTest($person->getid());
+    $person2->save();
+
+    $this->assertEqual($person2->getName(), $person->getName());
+    $this->assertEqual($person2->getSocialSecurity()->getCode(), $number->getCode());
+  }
+}
+
+?>

Modified: 3.x/trunk/limb/active_record/tests/cases/lmbARRecordSetDecoratorTest.class.php
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbARRecordSetDecoratorTest.class.php	2007-06-06 13:55:22 UTC (rev 5951)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbARRecordSetDecoratorTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -1,14 +1,14 @@
 <?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com 
- * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
  */
 lmb_require('limb/active_record/src/lmbARRecordSetDecorator.class.php');
 lmb_require('limb/core/src/lmbCollection.class.php');
-require_once(dirname(__FILE__) . '/lmbActiveRecordOneToManyRelationsTest.class.php');
+require_once(dirname(__FILE__) . '/lmbAROneToManyRelationsTest.class.php');
 
 class lmbARRecordSetDecoratorTest extends UnitTestCase
 {

Copied: 3.x/trunk/limb/active_record/tests/cases/lmbARRelationsDefinitionMethodsTest.class.php (from rev 5951, 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordRelationsDefinitionMethodsTest.class.php)
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbARRelationsDefinitionMethodsTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbARRelationsDefinitionMethodsTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -0,0 +1,136 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+lmb_require('limb/active_record/src/lmbActiveRecord.class.php');
+lmb_require('limb/dbal/src/lmbSimpleDb.class.php');
+
+class TestOneTableObjectWithRelationsByMethods extends lmbActiveRecord
+{
+  protected $_db_table_name = 'test_one_table_object';
+
+  public $relations = array();
+
+  function _defineRelations()
+  {
+    parent :: _defineRelations();
+
+    $this->_hasOne('has_one_relation', $has_one = array('field' => 'child_id',
+                                                        'class' => 'ChildClass'));
+    $this->relations['has_one_relation'] = $has_one;
+
+
+    $this->_hasOne('other_has_one_relation', $other_has_one = array('field' => 'other_child_id',
+                                                                    'class' => 'OtherChildClass'));
+    $this->relations['other_has_one_relation'] = $other_has_one;
+
+
+    $this->_hasMany('has_many_relation', $has_many = array('field' => 'parent_id',
+                                                           'class' => 'ManyChildClass'));
+    $this->relations['has_many_relation'] = $has_many;
+
+
+    $this->_hasMany('other_has_many_relation', $other_has_many = array('field' => 'other_parent_id',
+                                                                       'class' => 'OtherManyChildClass'));
+    $this->relations['other_has_many_relation'] = $other_has_many;
+
+
+    $this->_hasManyToMany('has_many_to_many_relation',  $many_to_many = array('field' => 'my_id',
+                                                                              'foreign_field' => 'important_id',
+                                                                              'class' => 'ImportantClass',
+                                                                              'table_name' => 'me2importand_class'));
+    $this->relations['has_many_to_many_relation'] = $many_to_many;
+
+
+    $this->_hasManyToMany('other_has_many_to_many_relation',  $other_many_to_many = array('field' => 'my_id',
+                                                                                          'foreign_field' => 'other_important_id',
+                                                                                          'class' => 'OtherImportantClass',
+                                                                                          'table_name' => 'me2other_importand_class'));
+    $this->relations['other_has_many_to_many_relation'] = $other_many_to_many;
+
+
+    $this->_belongsTo('belongs_to_relation', $belongs_to = array('field' => 'my_id',
+                                                                 'class' => 'ParentClass'));
+    $this->relations['belongs_to_relation'] = $belongs_to;
+
+
+    $this->_belongsTo('other_belongs_to_relation', $other_belongs_to = array('field' => 'my_id',
+                                                                             'class' => 'OtherParentClass'));
+    $this->relations['other_belongs_to_relation'] = $other_belongs_to;
+
+
+    $this->_manyBelongsTo('many_belongs_to_relation', $many_belongs_to = array('field' => 'parent_id',
+                                                                               'class' => 'ParentClass'));
+    $this->relations['many_belongs_to_relation'] = $many_belongs_to;
+
+
+    $this->_manyBelongsTo('other_many_belongs_to_relation', $other_many_belongs_to =  array('field' => 'parent_id',
+                                                                                            'class' => 'OtherParentClass'));
+    $this->relations['other_many_belongs_to_relation'] = $other_many_belongs_to;
+
+    $this->_composedOf('value_object', $value_object = array('field' => 'date_start',
+                                                             'class' => 'lmbDate',
+                                                             'getter' => 'getStamp'));
+
+    $this->relations['value_object'] = $value_object;
+
+
+    $this->_composedOf('other_value_object', $other_value_object = array('field' => 'date_end',
+                                                                         'class' => 'lmbDate',
+                                                                         'getter' => 'getStamp'));
+    $this->relations['other_value_object'] = $other_value_object;
+  }
+}
+
+class lmbARRelationsDefinitionMethodsTest extends UnitTestCase
+{
+  protected $object;
+
+  function setUp()
+  {
+    $this->object = new TestOneTableObjectWithRelationsByMethods();
+    $this->relations = $this->object->relations;
+  }
+
+  function testHasOne()
+  {
+    $this->assertEqual($this->object->getRelationInfo('has_one_relation'), $this->relations['has_one_relation']);
+    $this->assertEqual($this->object->getRelationInfo('other_has_one_relation'), $this->relations['other_has_one_relation']);
+  }
+
+  function testHasMany()
+  {
+    $this->assertEqual($this->object->getRelationInfo('has_many_relation'), $this->relations['has_many_relation']);
+    $this->assertEqual($this->object->getRelationInfo('other_has_many_relation'), $this->relations['other_has_many_relation']);
+  }
+
+  function testHasManyToMany()
+  {
+    $this->assertEqual($this->object->getRelationInfo('has_many_to_many_relation'), $this->relations['has_many_to_many_relation']);
+    $this->assertEqual($this->object->getRelationInfo('other_has_many_to_many_relation'), $this->relations['other_has_many_to_many_relation']);
+  }
+
+  function testBelongsTo()
+  {
+    $this->assertEqual($this->object->getRelationInfo('belongs_to_relation'), $this->relations['belongs_to_relation']);
+    $this->assertEqual($this->object->getRelationInfo('other_belongs_to_relation'), $this->relations['other_belongs_to_relation']);
+  }
+
+  function testManyBelongsTo()
+  {
+    $this->assertEqual($this->object->getRelationInfo('many_belongs_to_relation'), $this->relations['many_belongs_to_relation']);
+    $this->assertEqual($this->object->getRelationInfo('other_many_belongs_to_relation'), $this->relations['other_many_belongs_to_relation']);
+  }
+
+  function testComposedOf()
+  {
+    $this->assertEqual($this->object->getRelationInfo('value_object'), $this->relations['value_object']);
+    $this->assertEqual($this->object->getRelationInfo('other_value_object'), $this->relations['other_value_object']);
+  }
+}
+
+?>

Copied: 3.x/trunk/limb/active_record/tests/cases/lmbARSubclassingTest.class.php (from rev 5951, 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordSubclassingTest.class.php)
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbARSubclassingTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbARSubclassingTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -0,0 +1,185 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+lmb_require('limb/active_record/src/lmbActiveRecord.class.php');
+lmb_require('limb/dbal/src/lmbSimpleDb.class.php');
+
+class TestOneTableTypedObject extends lmbActiveRecord
+{
+  protected $_db_table_name = 'test_one_table_typed_object';
+}
+
+class FooOneTableTestObject extends TestOneTableTypedObject{}
+class BarFooOneTableTestObject extends FooOneTableTestObject{}
+
+class TypedLectureForTest extends lmbActiveRecord
+{
+  protected $_db_table_name = 'lecture_for_typed_test';
+  protected $_belongs_to = array('course' => array('field' => 'course_id',
+                                                   'class' => 'CourseForTestForTypedLecture'));
+}
+
+class FooLectureForTest extends TypedLectureForTest{}
+class BarFooLectureForTest extends FooLectureForTest{}
+
+class CourseForTestForTypedLecture extends lmbActiveRecord
+{
+  protected $_db_table_name = 'course_for_typed_test';
+  protected $_has_many = array('lectures' => array('field' => 'course_id',
+                                                   'class' => 'TypedLectureForTest'),
+                               'foo_lectures' => array('field' => 'course_id',
+                                                       'class' => 'FooLectureForTest'));
+}
+
+class lmbARSubclassingTest extends UnitTestCase
+{
+  protected $db;
+
+  function setUp()
+  {
+    $this->db = new lmbSimpleDb(lmbToolkit :: instance()->getDefaultDbConnection());
+    $this->_dbCleanUp();
+  }
+
+  function tearDown()
+  {
+    $this->_dbCleanUp();
+  }
+
+  function _dbCleanUp()
+  {
+    $this->db->delete('lecture_for_typed_test');
+    $this->db->delete('course_for_typed_test');
+    $this->db->delete('test_one_table_typed_object');
+  }
+
+  function testCreate()
+  {
+    $object1 = new FooOneTableTestObject();
+    $object1->setTitle('Some title');
+    $object1->save();
+
+    $object2 = new FooOneTableTestObject($object1->getId());
+    $this->assertEqual($object2->getTitle(), $object1->getTitle());
+
+    //parents are supertypes..
+    $object3 = new TestOneTableTypedObject($object1->getId());
+    $this->assertEqual($object3->getTitle(), $object1->getTitle());
+
+    try
+    {
+      //..while deeper subclasses are not
+      new BarFooOneTableTestObject($object1->getId());
+      $this->assertTrue(false);
+    }
+    catch(lmbARException $e){}
+  }
+
+  function testSupertypeDelete()
+  {
+    $foo = new FooOneTableTestObject();
+    $foo->setTitle('Some title');
+    $foo->save();
+
+    $bar = new BarFooOneTableTestObject();
+    $bar->setTitle('Another title');
+    $bar->save();
+
+    lmbActiveRecord :: delete('TestOneTableTypedObject');
+
+    $rs = lmbActiveRecord :: find('FooOneTableTestObject');
+    $this->assertEqual($rs->count(), 0);
+
+    $rs = lmbActiveRecord :: find('BarFooOneTableTestObject');
+    $this->assertEqual($rs->count(), 0);
+  }
+
+  function testTypedDelete()
+  {
+    $foo = new FooOneTableTestObject();
+    $foo->setTitle('Some title');
+    $foo->save();
+
+    $bar = new BarFooOneTableTestObject();
+    $bar->setTitle('Another title');
+    $bar->save();
+
+    lmbActiveRecord :: delete('BarFooOneTableTestObject');//removing subclass
+
+    $rs = lmbActiveRecord :: find('BarFooOneTableTestObject');
+    $this->assertEqual($rs->count(), 0);
+
+    $rs = lmbActiveRecord :: find('FooOneTableTestObject');//supertype stays
+    $this->assertEqual($rs->count(), 1);
+
+    lmbActiveRecord :: delete('FooOneTableTestObject');//removing supertype
+
+    $rs = lmbActiveRecord :: find('FooOneTableTestObject');
+    $this->assertEqual($rs->count(), 0);
+  }
+
+  function testFind()
+  {
+    $object1 = new FooOneTableTestObject();
+    $object1->setTitle('Some title');
+    $object1->save();
+
+    $object2 = new BarFooOneTableTestObject();
+    $object2->setTitle('Some other title');
+    $object2->save();
+
+    $rs = lmbActiveRecord :: find('FooOneTableTestObject');//supertype
+    $this->assertEqual($rs->count(), 2);
+    $this->assertIsA($rs->at(0), 'FooOneTableTestObject');
+    $this->assertIsA($rs->at(1), 'BarFooOneTableTestObject');
+
+    $rs = lmbActiveRecord :: find('BarFooOneTableTestObject');//subclass
+    $this->assertEqual($rs->count(), 1);
+    $this->assertIsA($rs->at(0), 'BarFooOneTableTestObject');
+  }
+
+  function testTypedRelationFind()
+  {
+    $course = new CourseForTestForTypedLecture();
+    $course->setTitle('Source1');
+    $course->save();
+
+    $lecture1 = new FooLectureForTest();
+    $lecture1->setTitle('Some title');
+    $lecture1->setCourse($course);
+    $lecture1->save();
+
+    $lecture2 = new BarFooLectureForTest();
+    $lecture2->setTitle('Some other title');
+    $lecture2->setCourse($course);
+    $lecture2->save();
+
+    $course->getLectures()->add($lecture1);
+    $course->getLectures()->add($lecture2);
+
+    $course2 = new CourseForTestForTypedLecture($course->getId());
+
+    $this->assertEqual($course2->getLectures()->count(), 2);//supertype by default
+    $this->assertIsA($course2->getLectures()->at(0), 'FooLectureForTest');
+    $this->assertIsA($course2->getLectures()->at(1), 'BarFooLectureForTest');
+
+    //narrowing selection but again its supertype for BarFooLectureForTest
+    $lectures = $course2->getLectures()->find(array('class' => 'FooLectureForTest'));
+
+    $this->assertEqual($lectures->count(), 2);
+    $this->assertIsA($lectures->at(0), 'FooLectureForTest');
+    $this->assertIsA($lectures->at(1), 'BarFooLectureForTest');
+
+    //narrowing more
+    $lectures = $course2->getLectures()->find(array('class' => 'BarFooLectureForTest'));
+    $this->assertEqual($lectures->count(), 1);
+    $this->assertIsA($lectures->at(0), 'BarFooLectureForTest');
+  }
+}
+
+?>

Copied: 3.x/trunk/limb/active_record/tests/cases/lmbARTransactionTest.class.php (from rev 5951, 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordTransactionTest.class.php)
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbARTransactionTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbARTransactionTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -0,0 +1,62 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+lmb_require('limb/active_record/src/lmbActiveRecord.class.php');
+lmb_require('limb/dbal/src/lmbSimpleDb.class.php');
+require_once(dirname(__FILE__) . '/lmbActiveRecordTest.class.php');//need TestOneTableObjectFailing
+
+class lmbARTransactionTest extends UnitTestCase
+{
+  function setUp()
+  {
+    $this->conn = lmbToolkit :: instance()->getDefaultDbConnection();
+    $this->db = new lmbSimpleDb($this->conn);
+
+    $this->_cleanUp();
+  }
+
+  function tearDown()
+  {
+    $this->_cleanUp();
+  }
+
+  function _cleanUp()
+  {
+    $this->db->delete('test_one_table_object');
+  }
+
+  function  testSaveInTransaction()
+  {
+    $this->conn->beginTransaction();
+
+    $obj = new TestOneTableObjectFailing();
+    $obj->setContent('hey');
+
+    $this->assertTrue($obj->trySave());
+
+    $this->conn->commitTransaction();
+
+    $this->assertEqual($this->db->count('test_one_table_object'), 1);
+  }
+
+  function  testSaveRollbacksTransaction()
+  {
+    $this->conn->beginTransaction();
+
+    $obj = new TestOneTableObjectFailing();
+    $obj->setContent('hey');
+    $obj->fail = new Exception('whatever');
+
+    $this->assertFalse($obj->trySave());
+
+    $this->conn->commitTransaction();
+
+    $this->assertEqual($this->db->count('test_one_table_object'), 0);
+  }
+}
+?>

Copied: 3.x/trunk/limb/active_record/tests/cases/lmbARValidationTest.class.php (from rev 5951, 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordValidationTest.class.php)
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbARValidationTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbARValidationTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -0,0 +1,340 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+lmb_require('limb/active_record/src/lmbActiveRecord.class.php');
+lmb_require('limb/validation/src/lmbValidator.class.php');
+lmb_require('limb/validation/src/lmbErrorList.class.php');
+require_once(dirname(__FILE__) . '/lmbActiveRecordTest.class.php');//need TestOneTableObjectFailing
+
+Mock :: generate('lmbValidator', 'MockValidator');
+Mock :: generate('lmbErrorList', 'MockErrorList');
+
+class lmbActiveRecordValidationStub extends lmbActiveRecord
+{
+  protected $_db_table_name = 'test_one_table_object';
+  protected $_insert_validator;
+  protected $_update_validator;
+
+  function setInsertValidator($validator)
+  {
+    $this->_insert_validator = $validator;
+  }
+
+  function setUpdateValidator($validator)
+  {
+    $this->_update_validator = $validator;
+  }
+
+  protected function _createInsertValidator()
+  {
+    return is_object($this->_insert_validator) ? $this->_insert_validator : new lmbValidator();
+  }
+
+  protected function _createUpdateValidator()
+  {
+    return is_object($this->_update_validator) ? $this->_update_validator : new lmbValidator();
+  }
+}
+
+class lmbARValidationTest extends UnitTestCase
+{
+  protected $db = null;
+
+  function setUp()
+  {
+    $toolkit = lmbToolkit :: save();
+    $this->db = new lmbSimpleDb($toolkit->getDefaultDbConnection());
+
+    $this->_cleanUp();
+  }
+
+  function tearDown()
+  {
+    $this->_cleanUp();
+
+    lmbToolkit :: restore();
+  }
+
+  function _cleanUp()
+  {
+    $this->db->delete('test_one_table_object');
+  }
+
+  function testGetErrorListReturnDefaultErrorList()
+  {
+    $object = $this->_createActiveRecord();
+    $this->assertIsA($object->getErrorList(), 'lmbErrorList');
+  }
+
+  function testValidateNew()
+  {
+    $error_list = new lmbErrorList();
+    $insert_validator = new MockValidator();
+    $update_validator = new MockValidator();
+
+    $object = $this->_createActiveRecord();
+    $object->setInsertValidator($insert_validator);
+    $object->setUpdateValidator($update_validator);
+
+    $object->set('annotation', 'blah-blah');
+
+    $insert_validator->expectOnce('setErrorList', array($error_list));
+    $insert_validator->expectOnce('validate', array(new ReferenceExpectation($object)));
+    $insert_validator->setReturnValue('validate', true);
+
+    $update_validator->expectNever('setErrorList');
+    $update_validator->expectNever('validate');
+
+    $this->assertTrue($object->validate($error_list));
+  }
+
+  function testGetErrorListReturnLastErrorListUsed()
+  {
+    $error_list = new lmbErrorList();
+    $insert_validator = new MockValidator();
+    $object = $this->_createActiveRecord();
+    $object->setInsertValidator($insert_validator);
+    $insert_validator->setReturnValue('validate', true);
+    $object->validate($error_list);
+
+    $this->assertReference($object->getErrorList(), $error_list);
+  }
+
+  function testValidateNewFailed()
+  {
+    $error_list = new lmbErrorList();
+    $insert_validator = new MockValidator();
+
+    $object = $this->_createActiveRecord();
+    $object->setInsertValidator($insert_validator);
+
+    $insert_validator->expectOnce('setErrorList', array($error_list));
+    $insert_validator->expectOnce('validate', array(new ReferenceExpectation($object)));
+    $error_list->addError('foo');//simulating validation error
+
+    $this->assertFalse($object->validate($error_list));
+  }
+
+  function testValidateExisting()
+  {
+    $error_list = new lmbErrorList();
+    $insert_validator = new MockValidator();
+    $update_validator = new MockValidator();
+
+    $object = $this->_createActiveRecordWithDataAndSave();
+    $object->setInsertValidator($insert_validator);
+    $object->setUpdateValidator($update_validator);
+
+    $update_validator->expectOnce('setErrorList', array($error_list));
+    $update_validator->expectOnce('validate', array(new ReferenceExpectation($object)));
+    $update_validator->setReturnValue('validate', true);
+
+    $insert_validator->expectNever('setErrorList');
+    $insert_validator->expectNever('validate');
+
+    $this->assertTrue($object->validate($error_list));
+  }
+
+  function testValidateExistingFailed()
+  {
+    $error_list = new lmbErrorList();
+    $update_validator = new MockValidator();
+
+    $object = $this->_createActiveRecordWithDataAndSave();
+    $object->setUpdateValidator($update_validator);
+
+    $update_validator->expectOnce('setErrorList', array($error_list));
+    $update_validator->expectOnce('validate', array(new ReferenceExpectation($object)));
+    $error_list->addError('foo');//simulating validation error
+
+    $this->assertFalse($object->validate($error_list));
+  }
+
+  function testDontInsertOnValidationError()
+  {
+    $object = $this->_createActiveRecord();
+
+    $error_list = new lmbErrorList();
+
+    $validator = new MockValidator();
+
+    $object->setInsertValidator($validator);
+
+    $object->set('annotation', $annotation = 'Super annotation');
+    $object->set('content', $content = 'Super content');
+    $object->set('news_date', $news_date = '2005-01-10');
+
+    $validator->expectOnce('setErrorList', array($error_list));
+    $validator->expectOnce('validate', array(new ReferenceExpectation($object)));
+    $error_list->addError('foo');//simulating validation error
+
+    try
+    {
+      $object->save($error_list);
+      $this->assertTrue(false);
+    }
+    catch(lmbValidationException $e)
+    {
+      $this->assertEqual($e->getErrorList()->export(), $error_list->getReadable()->export());
+    }
+
+    $this->assertEqual($this->db->count('test_one_table_object'), 0);
+  }
+
+  function testInsertOnValidationSuccess()
+  {
+    $object = $this->_createActiveRecord();
+
+    $error_list = new lmbErrorList();
+
+    $validator = new MockValidator();
+    $object->setInsertValidator($validator);
+
+    $object->set('annotation', $annotation = 'Super annotation');
+    $object->set('content', $content = 'Super content');
+    $object->set('news_date', $news_date = '2005-01-10');
+
+    $validator->expectOnce('setErrorList', array($error_list));
+    $validator->expectOnce('validate', array(new ReferenceExpectation($object)));
+    $validator->setReturnValue('validate', true);
+
+    $object->save($error_list);
+
+    $this->assertEqual($this->db->count('test_one_table_object'), 1);
+  }
+
+  function testDontUpdateOnValidationError()
+  {
+    $object = $this->_createActiveRecordWithDataAndSave();
+    $old_annotation = $object->get('annotation');
+
+    $error_list = new lmbErrorList();
+
+    $validator = new MockValidator();
+    $object->setUpdateValidator($validator);
+
+    $object->set('annotation', $annotation = 'New annotation ' . time());
+
+    $validator->expectOnce('setErrorList', array($error_list));
+    $validator->expectOnce('validate', array(new ReferenceExpectation($object)));
+    $error_list->addError('foo');//simulating validation error
+
+    try
+    {
+      $object->save($error_list);
+      $this->assertTrue(false);
+    }
+    catch(lmbValidationException $e)
+    {
+      $this->assertEqual($e->getErrorList()->export(), $error_list->getReadable()->export());
+    }
+
+    $record = $this->db->getFirstRecordFrom('test_one_table_object');
+    $this->assertEqual($record->get('annotation'), $old_annotation);
+  }
+
+  function testUpdateOnValidationSuccess()
+  {
+    $object = $this->_createActiveRecordWithDataAndSave();
+
+    $error_list = new lmbErrorList();
+
+    $validator = new MockValidator();
+    $object->setUpdateValidator($validator);
+
+    $object->set('annotation', $annotation = 'New annotation ' . time());
+
+    $validator->expectOnce('setErrorList', array($error_list));
+    $validator->expectOnce('validate', array(new ReferenceExpectation($object)));
+    $validator->setReturnValue('validate', true);
+
+    $object->save($error_list);
+
+    $record = $this->db->getFirstRecordFrom('test_one_table_object');
+    $this->assertEqual($record->get('annotation'), $annotation);
+  }
+
+  function testSaveSkipValidation()
+  {
+    $object = $this->_createActiveRecordWithDataAndSave();
+
+    $validator = new MockValidator();
+    $object->setUpdateValidator($validator);
+
+    $object->set('annotation', $annotation = 'New annotation ' . time());
+
+    $validator->expectNever('validate');
+
+    $object->saveSkipValidation();
+
+    $record = $this->db->getFirstRecordFrom('test_one_table_object');
+    $this->assertEqual($record->get('annotation'), $annotation);
+  }
+
+  function testIsValid()
+  {
+    $object = $this->_createActiveRecordWithDataAndSave();
+    $this->assertTrue($object->isValid());
+  }
+
+  function testIsNotValid()
+  {
+    $error_list = new lmbErrorList();
+
+    $object = $this->_createActiveRecordWithDataAndSave();
+    $this->assertTrue($object->isValid());
+
+    $error_list->addError('whatever');//actually it's a dirty simulation but that's how it works really
+
+    $object->save($error_list);
+    $this->assertFalse($object->isValid());
+  }
+
+  function testValidationExceptionIsNotAddedToErrorList()
+  {
+    $error_list = new lmbErrorList();
+
+    $object = new TestOneTableObjectFailing();
+    $object->setContent('A-a-a-a');
+    $object->fail = new lmbValidationException('foo', $error_list);
+
+    $this->assertFalse($object->trySave($error_list));
+    $this->assertTrue($error_list->isEmpty());
+  }
+
+  function testNonValidationExceptionIsAddedToErrorList()
+  {
+    $error_list = new lmbErrorList();
+
+    $object = new TestOneTableObjectFailing();
+    $object->setContent('A-a-a-a');
+    $object->fail = new Exception('yo-yo');
+
+    $this->assertFalse($object->trySave($error_list));
+    $this->assertFalse($error_list->isEmpty());
+    $this->assertEqual(sizeof($error_list), 1);
+    $this->assertPattern('~yo-yo~', $error_list[0]->getMessage());
+  }
+
+  function _createActiveRecord()
+  {
+    $object = new lmbActiveRecordValidationStub();
+    return $object;
+  }
+
+  protected function _createActiveRecordWithDataAndSave()
+  {
+    $object = $this->_createActiveRecord();
+    $object->set('annotation', 'Annotation ' . time());
+    $object->set('content', 'Content ' . time());
+    $object->set('news_date', date("Y-m-d", time()));
+    $object->save();
+    return $object;
+  }
+}
+?>

Copied: 3.x/trunk/limb/active_record/tests/cases/lmbARValueObjectTest.class.php (from rev 5951, 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordValueObjectTest.class.php)
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbARValueObjectTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbARValueObjectTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -0,0 +1,127 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+lmb_require('limb/active_record/src/lmbActiveRecord.class.php');
+lmb_require('limb/dbal/src/lmbSimpleDb.class.php');
+
+class TestingValueObject
+{
+  var $value;
+
+  function __construct($value)
+  {
+    $this->value = $value;
+  }
+
+  function getValue()
+  {
+    return $this->value;
+  }
+}
+
+class LessonForTest extends lmbActiveRecord
+{
+  protected $_composed_of = array('date_start' => array('field' => 'date_start',
+                                                        'class' => 'TestingValueObject',
+                                                        'getter' => 'getValue'),
+                                  'date_end' => array('field' => 'date_end',
+                                                      'class' => 'TestingValueObject',
+                                                      'getter' => 'getValue'));
+}
+
+class LazyLessonForTest extends lmbActiveRecord
+{
+  protected $_db_table_name = 'lesson_for_test';
+  protected $_lazy_attributes = array('date_start');
+  protected $_composed_of = array('date_start' => array('field' => 'date_start',
+                                                        'class' => 'TestingValueObject',
+                                                        'getter' => 'getValue'),
+                                  'date_end' => array('field' => 'date_end',
+                                                      'class' => 'TestingValueObject',
+                                                      'getter' => 'getValue'));
+
+}
+
+class lmbARValueObjectTest extends UnitTestCase
+{
+  function setUp()
+  {
+    $this->_dbCleanUp();
+  }
+
+  function tearDown()
+  {
+    $this->_dbCleanUp();
+  }
+
+  function _dbCleanUp()
+  {
+    lmbActiveRecord :: delete('LessonForTest');
+  }
+
+  function testNewObjectReturnsNullValueObjects()
+  {
+    $lesson = new LessonForTest();
+    $this->assertNull($lesson->getDateStart());
+    $this->assertNull($lesson->getDateEnd());
+  }
+
+  function testSaveLoadValueObjects()
+  {
+    $lesson = new LessonForTest();
+
+    $lesson->setDateStart(new TestingValueObject($v1 = time()));
+    $lesson->setDateEnd(new TestingValueObject($v2 = time() + 100));
+
+    $lesson->save();
+
+    $lesson2 = lmbActiveRecord :: findById('LessonForTest', $lesson->getId());
+    $this->assertEqual($lesson2->getDateStart()->getValue(), $v1);
+    $this->assertEqual($lesson2->getDateEnd()->getValue(), $v2);
+  }
+
+  function testGenericGetReturnsAlreadyExistingObject()
+  {
+    $lesson = new LessonForTest();
+
+    $lesson->setDateStart(new TestingValueObject($v1 = time() - 100));
+    $lesson->setDateEnd(new TestingValueObject($v2 = time() + 100));
+
+    $this->assertEqual($lesson->get('date_start')->getValue(), $v1);
+    $this->assertEqual($lesson->get('date_end')->getValue(), $v2);
+  }
+
+  function testLazyValueObjects()
+  {
+    $lesson = new LessonForTest();
+
+    $lesson->setDateStart(new TestingValueObject($v1 = time()));
+    $lesson->setDateEnd(new TestingValueObject($v2 = time() + 100));
+
+    $lesson->save();
+
+    $lesson2 = new LazyLessonForTest($lesson->getId());
+
+    $this->assertEqual($lesson2->getDateStart()->getValue(), $v1);
+    $this->assertEqual($lesson2->getDateEnd()->getValue(), $v2);
+  }
+
+  function testValueObjectsAreImportedProperly()
+  {
+    $lesson = new LessonForTest();
+    $lesson->setDateStart(new TestingValueObject($v1 = time()));
+    $lesson->setDateEnd(new TestingValueObject($v2 = time() + 100));
+
+    $lesson2 = new LessonForTest($lesson->export());
+
+    $this->assertEqual($lesson2->getDateStart()->getValue(), $v1);
+    $this->assertEqual($lesson2->getDateEnd()->getValue(), $v2);
+  }
+}
+
+?>

Deleted: 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordAttributesLazyLoadingTest.class.php
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordAttributesLazyLoadingTest.class.php	2007-06-06 13:55:22 UTC (rev 5951)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordAttributesLazyLoadingTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -1,90 +0,0 @@
-<?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com 
- * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
- */
-lmb_require('limb/active_record/src/lmbActiveRecord.class.php');
-lmb_require('limb/dbal/src/lmbSimpleDb.class.php');
-lmb_require('limb/dbal/src/lmbTableGateway.class.php');
-
-class LazyTestOneTableObject extends lmbActiveRecord
-{
-  protected $_db_table_name = 'test_one_table_object';
-  protected $_lazy_attributes = array('annotation', 'content');
-}
-
-class lmbActiveRecordAttributesLazyLoadingTest extends UnitTestCase
-{
-  var $conn = null;
-  var $db = null;
-
-  function setUp()
-  {
-    $this->conn = lmbToolkit :: instance()->getDefaultDbConnection();
-    $this->db = new lmbSimpleDb($this->conn);
-    $this->_cleanUp();
-  }
-
-  function tearDown()
-  {
-    $this->_cleanUp();
-  }
-
-  function _cleanUp()
-  {
-    $this->db->delete('test_one_table_object');
-  }
-
-  function testLazyFind()
-  {
-    $object = $this->_createActiveRecord($annotation = 'Some annotation', $content = 'Some content');
-    $object2 = lmbActiveRecord :: findById('LazyTestOneTableObject', $object->getId());
-
-    $this->_checkLazyness($object2, $annotation, $content);
-  }
-
-  function testLazyLoadById()
-  {
-    $object = $this->_createActiveRecord($annotation = 'Some annotation', $content = 'Some content');
-
-    $object2 = new LazyTestOneTableObject();
-    $object2->loadById($object->getId());
-
-    $this->_checkLazyness($object2, $annotation, $content);
-  }
-
-  function testExportIsNotLazy()
-  {
-    $object = $this->_createActiveRecord($annotation = 'Some annotation', $content = 'Some content');
-    $object2 = lmbActiveRecord :: findById('LazyTestOneTableObject', $object->getId());
-    $exported = $object2->export();
-    $this->assertEqual($exported['annotation'], $annotation);
-    $this->assertEqual($exported['content'], $content);
-  }
-
-  protected function _checkLazyness($object, $annotation, $content)
-  {
-    $this->assertTrue($object->hasAttribute('news_date'));
-
-    $this->assertFalse($object->hasAttribute('annotation'));
-    $this->assertEqual($object->getAnnotation(), $annotation);
-    $this->assertTrue($object->hasAttribute('annotation'));
-
-    $this->assertFalse($object->hasAttribute('content'));
-    $this->assertEqual($object->getContent(), $content);
-    $this->assertTrue($object->hasAttribute('content'));
-  }
-
-  protected function _createActiveRecord($annotation, $content)
-  {
-    $object = new LazyTestOneTableObject();
-    $object->setAnnotation($annotation);
-    $object->setContent($content);
-    $object->save();
-    return $object;
-  }
-}
-?>

Deleted: 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordAutoTimesTest.class.php
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordAutoTimesTest.class.php	2007-06-06 13:55:22 UTC (rev 5951)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordAutoTimesTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -1,86 +0,0 @@
-<?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com 
- * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
- */
-lmb_require('limb/active_record/src/lmbActiveRecord.class.php');
-lmb_require('limb/dbal/src/lmbSimpleDb.class.php');
-
-class TestAutoTimesObject extends lmbActiveRecord
-{
-  protected $_db_table_name = 'test_auto_times_object';
-}
-
-class lmbActiveRecordAutoTimesTest extends UnitTestCase
-{
-  var $conn;
-  var $db;
-
-  function setUp()
-  {
-    $toolkit = lmbToolkit :: save();
-    $this->conn = $toolkit->getDefaultDbConnection();
-    $this->db = new lmbSimpleDb($this->conn);
-
-    $this->_cleanUp();
-  }
-
-  function tearDown()
-  {
-    $this->_cleanUp();
-
-    lmbToolkit :: restore();
-  }
-
-  function _cleanUp()
-  {
-    $this->db->delete('test_auto_times_object');
-  }
-
-  function testSetTimesAutomaticallyOnCreate()
-  {
-    $time = time();
-    $object = new TestAutoTimesObject();
-    $object->setContent('whatever');
-
-    $id = $object->save();
-
-    $object2 = new TestAutoTimesObject($id);
-    $this->assertTrue($object2->getUpdateTime() >= $time);
-    $this->assertTrue($object2->getCreateTime() >= $time);
-
-    $this->assertEqual($object->getUpdateTime(), $object2->getUpdateTime());
-    $this->assertEqual($object->getCreateTime(), $object2->getCreateTime());
-  }
-
-  function testSetTimesAutomaticallyOnUpdate()
-  {
-    $time = time();
-    $object = new TestAutoTimesObject();
-    $object->setContent('whatever');
-
-    $object->save();
-    $ctime1 =  $object->getCreateTime();
-    $utime1 =  $object->getUpdateTime();
-
-    sleep(1);
-
-    $object->setContent('whatever2');//without this object is considered to be not dirty
-    $object->save();
-    $ctime2 =  $object->getCreateTime();
-    $utime2 =  $object->getUpdateTime();
-
-    $this->assertTrue($ctime1 >= $time);
-    $this->assertTrue($utime1 >= $time);
-    $this->assertEqual($ctime1, $ctime2);
-    $this->assertTrue($utime2 > $utime1);
-
-    $object2 = new TestAutoTimesObject($object->getId());
-    $this->assertEqual($object2->getCreateTime(), $ctime1);
-    $this->assertEqual($object2->getUpdateTime(), $utime2);
-  }
-}
-?>

Deleted: 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordDirtyTest.class.php
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordDirtyTest.class.php	2007-06-06 13:55:22 UTC (rev 5951)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordDirtyTest.class.php	2007-06-06 14:28:07 UTC (rev 5952)
@@ -1,249 +0,0 @@
-<?php
-/*
- * Limb PHP Framework
- *
- * @link http://limb-project.com 
- * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
- * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
- */
-lmb_require('limb/active_record/src/lmbActiveRecord.class.php');
-lmb_require('limb/dbal/src/lmbSimpleDb.class.php');
-lmb_require('limb/dbal/src/lmbTableGateway.class.php');
-require_once(dirname(__FILE__) . '/lmbActiveRecordTest.class.php');
-require_once(dirname(__FILE__) . '/lmbActiveRecordOneToManyRelationsTest.class.php');
-require_once(dirname(__FILE__) . '/lmbActiveRecordValueObjectTest.class.php');
-require_once(dirname(__FILE__) . '/lmbActiveRecordOneToOneRelationsTest.class.php');
-
-class lmbActiveRecordDirtyTest extends UnitTestCase
-{
-  var $conn = null;
-  var $db = null;
-
-  function setUp()
-  {
-    $toolkit = lmbToolkit :: save();
-    $this->conn = $toolkit->getDefaultDbConnection();
-    $this->db = new lmbSimpleDb($this->conn);
-
-    $this->_cleanUp();
-  }
-
-  function tearDown()
-  {
-    $this->_cleanUp();
-    lmbToolkit :: restore();
-  }
-
-  function _cleanUp()
-  {
-    lmbActiveRecord :: delete('TestOneTableObject');
-    lmbActiveRecord :: delete('LessonForTest');
-    lmbActiveRecord :: delete('CourseForTest');
-    lmbActiveRecord :: delete('LectureForTest');
-  }
-
-  function testJustFoundObjectIsNotDirty()
-  {
-    $object = new TestOneTableObject();
-    $object->setContent('test');
-    $object->save();
-
-    $object2 = lmbActiveRecord :: find('TestOneTableObject', $object->getId());
-    $this->assertFalse($object2->isDirty());
-  }
-
-  function testJustLoadedByIdObjectIsNotDirty()
-  {
-    $object = new TestOneTableObject();
-    $object->setContent('test');
-    $object->save();
-
-    $object2 = new TestOneTableObject($object->getId());
-    $this->assertFalse($object2->isDirty());
-  }
-
-  function testMarkDirty()
-  {
-    $object = new TestOneTableObject();
-    $this->assertFalse($object->isDirty());
-    $object->markDirty();
-    $this->assertTrue($object->isDirty());
-  }
-
-  function testObjectBecomesDirtyIfAttributeIsSetWithSetter()
-  {
-    $object = new TestOneTableObject();
-    $this->assertFalse($object->isDirty());
-    $object->setContent('hey');
-    $this->assertTrue($object->isDirty());
-  }
-
-  function testDirtyObjectBecomesCleanOnceSaved()
-  {
-    $object = new TestOneTableObject();
-    $object->setContent('whatever');
-    $this->assertTrue($object->isDirty());
-    $object->save();
-    $this->assertFalse($object->isDirty());
-  }
-
-  function testNonDirtyObjectIsNotUpdated()
-  {
-    $object = new TestOneTableObjectWithHooks();
-    $object->setContent('whatever');
-
-    ob_start();
-    $object->save();
-    $str = ob_get_contents();
-    ob_end_clean();
-    $this->assertEqual($str, '|on_before_save||on_before_create||on_validate||on_save||on_create||on_after_create||on_after_save|');
-
-    ob_start();
-    $object->save();
-    $str = ob_get_contents();
-    ob_end_clean();
-    $this->assertEqual($str, '|on_before_save||on_after_save|');
-  }
-
-  function testSettingNewParentObjectDoesntMakeNewObjectDirty()
-  {
-    $course = new CourseForTest();
-
-    $lecture = new LectureForTest();
-    $lecture->setCourse($course);
-
-    $this->assertTrue($lecture->isNew());
-    $this->assertFalse($lecture->isDirty());
-  }
-
-  function testParentIsSavedEvenForCleanObject()
-  {
-    $course = new CourseForTest();
-    $course->setTitle('course');
-    $course->save();
-
-    $lecture = new LectureForTest();
-    $lecture->setCourse($course);
-    $lecture->save();
-
-    $lecture2 = new LectureForTest($lecture->getId());
-    $this->assertEqual($lecture2->getCourse()->getTitle(), 'course');
-  }
-
-  function testChangingSavedParentObjectDoesntMakeObjectDirty()
-  {
-    $course = new CourseForTest();
-    $course->setTitle('course');
-    $course->save();
-
-    $lecture = new LectureForTest();
-    $lecture->setCourse($course);
-    $lecture->save();
-