MDL-28021 Completion system can create inconsistent database rows
This change includes:
(1) update deletes older versions of inconsistent rows
(2) update drops one index and replaces it with a new unique index
(3) fixed to ensure that when it decides whether to insert or update
it uses current database state and not cached info
(4) unit tests updated to test #3
Conflicts:
lib/db/upgrade.php
version.php
This commit is contained in:
committed by
Eloy Lafuente (stronk7)
parent
8e0733f4d8
commit
a854bca3cf
@@ -6,6 +6,7 @@ require_once($CFG->libdir.'/completionlib.php');
|
||||
|
||||
global $DB;
|
||||
Mock::generate(get_class($DB), 'mock_database');
|
||||
Mock::generate('moodle_transaction', 'mock_transaction');
|
||||
|
||||
Mock::generatePartial('completion_info','completion_cutdown',
|
||||
array('delete_all_state','get_tracked_users','update_state',
|
||||
@@ -452,24 +453,40 @@ WHERE
|
||||
function test_internal_set_data() {
|
||||
global $DB,$SESSION;
|
||||
|
||||
$cm=(object)array('course'=>42,'id'=>13);
|
||||
$c=new completion_info((object)array('id'=>42));
|
||||
$cm = (object)array('course' => 42,'id' => 13);
|
||||
$c = new completion_info((object)array('id' => 42));
|
||||
|
||||
// 1) Test with new data
|
||||
$data=(object)array('id'=>0,'userid'=>314159);
|
||||
$DB->setReturnValueAt(0,'insert_record',4);
|
||||
$DB->expectAt(0,'insert_record',array('course_modules_completion',$data));
|
||||
$c->internal_set_data($cm,$data);
|
||||
$this->assertEqual(4,$data->id);
|
||||
$this->assertEqual(array(42=>array(13=>$data)),$SESSION->completioncache);
|
||||
$data = (object)array('id'=>0, 'userid' => 314159, 'coursemoduleid' => 99);
|
||||
$DB->setReturnValueAt(0, 'start_delegated_transaction', new mock_transaction());
|
||||
$DB->setReturnValueAt(0, 'insert_record', 4);
|
||||
$DB->expectAt(0, 'get_field', array('course_modules_completion', 'id',
|
||||
array('coursemoduleid' => 99, 'userid' => 314159)));
|
||||
$DB->expectAt(0, 'insert_record', array('course_modules_completion', $data));
|
||||
$c->internal_set_data($cm, $data);
|
||||
$this->assertEqual(4, $data->id);
|
||||
$this->assertEqual(array(42 => array(13 => $data)), $SESSION->completioncache);
|
||||
|
||||
// 2) Test with existing data and for different user (not cached)
|
||||
unset($SESSION->completioncache);
|
||||
$d2=(object)array('id'=>7,'userid'=>17);
|
||||
$DB->expectAt(0,'update_record',array('course_modules_completion',$d2));
|
||||
$c->internal_set_data($cm,$d2);
|
||||
$d2 = (object)array('id' => 7, 'userid' => 17, 'coursemoduleid' => 66);
|
||||
$DB->setReturnValueAt(1, 'start_delegated_transaction', new mock_transaction());
|
||||
$DB->expectAt(0,'update_record', array('course_modules_completion', $d2));
|
||||
$c->internal_set_data($cm, $d2);
|
||||
$this->assertFalse(isset($SESSION->completioncache));
|
||||
|
||||
// 3) Test where it THINKS the data is new (from cache) but actually
|
||||
// in the database it has been set since
|
||||
// 1) Test with new data
|
||||
$data = (object)array('id'=>0, 'userid' => 314159, 'coursemoduleid' => 99);
|
||||
$DB->setReturnValueAt(2, 'start_delegated_transaction', new mock_transaction());
|
||||
$DB->setReturnValueAt(1, 'get_field', 13);
|
||||
$DB->expectAt(1, 'get_field', array('course_modules_completion', 'id',
|
||||
array('coursemoduleid' => 99, 'userid' => 314159)));
|
||||
$d3 = (object)array('id' => 13, 'userid' => 314159, 'coursemoduleid' => 99);
|
||||
$DB->expectAt(1,'update_record', array('course_modules_completion', $d3));
|
||||
$c->internal_set_data($cm, $data);
|
||||
|
||||
$DB->tally();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user