8 class JobQueueTest
extends MediaWikiTestCase
{
9 protected $old = array();
11 function __construct( $name = null, array $data = array(), $dataName = '' ) {
12 parent
::__construct( $name, $data, $dataName );
14 $this->tablesUsed
[] = 'job';
17 protected function setUp() {
20 $this->old
['wgMemc'] = $wgMemc;
21 $wgMemc = new HashBagOStuff();
22 $this->queueRand
= JobQueue
::factory( array( 'class' => 'JobQueueDB',
23 'wiki' => wfWikiID(), 'type' => 'null', 'order' => 'random' ) );
24 $this->queueRandTTL
= JobQueue
::factory( array( 'class' => 'JobQueueDB',
25 'wiki' => wfWikiID(), 'type' => 'null', 'order' => 'random', 'claimTTL' => 10 ) );
26 $this->queueFifo
= JobQueue
::factory( array( 'class' => 'JobQueueDB',
27 'wiki' => wfWikiID(), 'type' => 'null', 'order' => 'fifo' ) );
28 $this->queueFifoTTL
= JobQueue
::factory( array( 'class' => 'JobQueueDB',
29 'wiki' => wfWikiID(), 'type' => 'null', 'order' => 'fifo', 'claimTTL' => 10 ) );
32 protected function tearDown() {
35 foreach ( array( 'queueRand', 'queueRandTTL', 'queueFifo', 'queueFifoTTL' ) as $q ) {
37 $job = $this->$q->pop();
38 if ( $job ) $this->$q->ack( $job );
41 $this->queueRand
= null;
42 $this->queueRandTTL
= null;
43 $this->queueFifo
= null;
44 $this->queueFifoTTL
= null;
45 $wgMemc = $this->old
['wgMemc'];
49 * @dataProvider provider_queueLists
51 function testProperties( $queue, $order, $recycles, $desc ) {
52 $queue = $this->$queue;
54 $this->assertEquals( wfWikiID(), $queue->getWiki(), "Proper wiki ID ($desc)" );
55 $this->assertEquals( 'null', $queue->getType(), "Proper job type ($desc)" );
59 * @dataProvider provider_queueLists
61 function testBasicOperations( $queue, $order, $recycles, $desc ) {
62 $queue = $this->$queue;
63 $this->assertTrue( $queue->isEmpty(), "Queue is empty ($desc)" );
65 $queue->flushCaches();
66 $this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
67 $this->assertEquals( 0, $queue->getAcquiredCount(), "Queue is empty ($desc)" );
69 $this->assertTrue( $queue->push( $this->newJob() ), "Push worked ($desc)" );
70 $this->assertTrue( $queue->batchPush( array( $this->newJob() ) ), "Push worked ($desc)" );
72 $this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
74 $queue->flushCaches();
75 $this->assertEquals( 2, $queue->getSize(), "Queue size is correct ($desc)" );
76 $this->assertEquals( 0, $queue->getAcquiredCount(), "No jobs active ($desc)" );
78 $job1 = $queue->pop();
79 $this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
81 $queue->flushCaches();
82 $this->assertEquals( 1, $queue->getSize(), "Queue size is correct ($desc)" );
84 $queue->flushCaches();
86 $this->assertEquals( 1, $queue->getAcquiredCount(), "Active job count ($desc)" );
88 $this->assertEquals( 0, $queue->getAcquiredCount(), "Active job count ($desc)" );
91 $job2 = $queue->pop();
92 $this->assertTrue( $queue->isEmpty(), "Queue is empty ($desc)" );
93 $this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
95 $queue->flushCaches();
97 $this->assertEquals( 2, $queue->getAcquiredCount(), "Active job count ($desc)" );
99 $this->assertEquals( 0, $queue->getAcquiredCount(), "Active job count ($desc)" );
102 $queue->ack( $job1 );
104 $queue->flushCaches();
106 $this->assertEquals( 1, $queue->getAcquiredCount(), "Active job count ($desc)" );
108 $this->assertEquals( 0, $queue->getAcquiredCount(), "Active job count ($desc)" );
111 $queue->ack( $job2 );
113 $queue->flushCaches();
114 $this->assertEquals( 0, $queue->getAcquiredCount(), "Active job count ($desc)" );
118 * @dataProvider provider_queueLists
120 function testBasicDeduplication( $queue, $order, $recycles, $desc ) {
121 $queue = $this->$queue;
123 $this->assertTrue( $queue->isEmpty(), "Queue is empty ($desc)" );
125 $queue->flushCaches();
126 $this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
127 $this->assertEquals( 0, $queue->getAcquiredCount(), "Queue is empty ($desc)" );
129 $this->assertTrue( $queue->batchPush(
130 array( $this->newDedupedJob(), $this->newDedupedJob(), $this->newDedupedJob() ) ),
131 "Push worked ($desc)" );
133 $this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
135 $queue->flushCaches();
136 $this->assertEquals( 1, $queue->getSize(), "Queue size is correct ($desc)" );
137 $this->assertEquals( 0, $queue->getAcquiredCount(), "No jobs active ($desc)" );
139 $this->assertTrue( $queue->batchPush(
140 array( $this->newDedupedJob(), $this->newDedupedJob(), $this->newDedupedJob() ) ),
141 "Push worked ($desc)" );
143 $this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
145 $queue->flushCaches();
146 $this->assertEquals( 1, $queue->getSize(), "Queue size is correct ($desc)" );
147 $this->assertEquals( 0, $queue->getAcquiredCount(), "No jobs active ($desc)" );
149 $job1 = $queue->pop();
150 $this->assertTrue( $queue->isEmpty(), "Queue is empty ($desc)" );
152 $queue->flushCaches();
153 $this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
155 $this->assertEquals( 1, $queue->getAcquiredCount(), "Active job count ($desc)" );
157 $this->assertEquals( 0, $queue->getAcquiredCount(), "Active job count ($desc)" );
160 $queue->ack( $job1 );
162 $queue->flushCaches();
163 $this->assertEquals( 0, $queue->getAcquiredCount(), "Active job count ($desc)" );
167 * @dataProvider provider_queueLists
169 function testRootDeduplication( $queue, $order, $recycles, $desc ) {
170 $queue = $this->$queue;
172 $this->assertTrue( $queue->isEmpty(), "Queue is empty ($desc)" );
174 $queue->flushCaches();
175 $this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
176 $this->assertEquals( 0, $queue->getAcquiredCount(), "Queue is empty ($desc)" );
178 $id = wfRandomString( 32 );
179 $root1 = Job
::newRootJobParams( "nulljobspam:$id" ); // task ID/timestamp
180 for ( $i=0; $i<5; ++
$i ) {
181 $this->assertTrue( $queue->push( $this->newJob( 0, $root1 ) ), "Push worked ($desc)" );
183 $queue->deduplicateRootJob( $this->newJob( 0, $root1 ) );
184 sleep( 1 ); // roo job timestamp will increase
185 $root2 = Job
::newRootJobParams( "nulljobspam:$id" ); // task ID/timestamp
186 $this->assertNotEquals( $root1['rootJobTimestamp'], $root2['rootJobTimestamp'],
187 "Root job signatures have different timestamps." );
188 for ( $i=0; $i<5; ++
$i ) {
189 $this->assertTrue( $queue->push( $this->newJob( 0, $root2 ) ), "Push worked ($desc)" );
191 $queue->deduplicateRootJob( $this->newJob( 0, $root2 ) );
193 $this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
195 $queue->flushCaches();
196 $this->assertEquals( 10, $queue->getSize(), "Queue size is correct ($desc)" );
197 $this->assertEquals( 0, $queue->getAcquiredCount(), "No jobs active ($desc)" );
202 $job = $queue->pop();
207 if ( $job instanceof DuplicateJob
) ++
$dupcount;
210 $this->assertEquals( 10, count( $jobs ), "Correct number of jobs popped ($desc)" );
211 $this->assertEquals( 5, $dupcount, "Correct number of duplicate jobs popped ($desc)" );
215 * @dataProvider provider_fifoQueueLists
217 function testJobOrder( $queue, $recycles, $desc ) {
218 $queue = $this->$queue;
220 $this->assertTrue( $queue->isEmpty(), "Queue is empty ($desc)" );
222 $queue->flushCaches();
223 $this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
224 $this->assertEquals( 0, $queue->getAcquiredCount(), "Queue is empty ($desc)" );
226 for ( $i=0; $i<10; ++
$i ) {
227 $this->assertTrue( $queue->push( $this->newJob( $i ) ), "Push worked ($desc)" );
230 for ( $i=0; $i<10; ++
$i ) {
231 $job = $queue->pop();
232 $this->assertTrue( $job instanceof Job
, "Jobs popped from queue ($desc)" );
233 $params = $job->getParams();
234 $this->assertEquals( $i, $params['i'], "Job popped from queue is FIFO ($desc)" );
238 $this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
240 $queue->flushCaches();
241 $this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
242 $this->assertEquals( 0, $queue->getAcquiredCount(), "No jobs active ($desc)" );
245 function provider_queueLists() {
247 array( 'queueRand', 'rand', false, 'Random queue without ack()' ),
248 array( 'queueRandTTL', 'rand', true, 'Random queue with ack()' ),
249 array( 'queueFifo', 'fifo', false, 'Ordered queue without ack()' ),
250 array( 'queueFifoTTL', 'fifo', true, 'Ordered queue with ack()' )
254 function provider_fifoQueueLists() {
256 array( 'queueFifo', false, 'Ordered queue without ack()' ),
257 array( 'queueFifoTTL', true, 'Ordered queue with ack()' )
261 function newJob( $i = 0, $rootJob = array() ) {
262 return new NullJob( Title
::newMainPage(),
263 array( 'lives' => 0, 'usleep' => 0, 'removeDuplicates' => 0, 'i' => $i ) +
$rootJob );
266 function newDedupedJob( $i = 0, $rootJob = array() ) {
267 return new NullJob( Title
::newMainPage(),
268 array( 'lives' => 0, 'usleep' => 0, 'removeDuplicates' => 1, 'i' => $i ) +
$rootJob );