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();
39 $this->$q->ack( $job );
43 $this->queueRand
= null;
44 $this->queueRandTTL
= null;
45 $this->queueFifo
= null;
46 $this->queueFifoTTL
= null;
47 $wgMemc = $this->old
['wgMemc'];
51 * @dataProvider provider_queueLists
53 function testProperties( $queue, $order, $recycles, $desc ) {
54 $queue = $this->$queue;
56 $this->assertEquals( wfWikiID(), $queue->getWiki(), "Proper wiki ID ($desc)" );
57 $this->assertEquals( 'null', $queue->getType(), "Proper job type ($desc)" );
61 * @dataProvider provider_queueLists
63 function testBasicOperations( $queue, $order, $recycles, $desc ) {
64 $queue = $this->$queue;
65 $this->assertTrue( $queue->isEmpty(), "Queue is empty ($desc)" );
67 $queue->flushCaches();
68 $this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
69 $this->assertEquals( 0, $queue->getAcquiredCount(), "Queue is empty ($desc)" );
71 $this->assertTrue( $queue->push( $this->newJob() ), "Push worked ($desc)" );
72 $this->assertTrue( $queue->batchPush( array( $this->newJob() ) ), "Push worked ($desc)" );
74 $this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
76 $queue->flushCaches();
77 $this->assertEquals( 2, $queue->getSize(), "Queue size is correct ($desc)" );
78 $this->assertEquals( 0, $queue->getAcquiredCount(), "No jobs active ($desc)" );
80 $job1 = $queue->pop();
81 $this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
83 $queue->flushCaches();
84 $this->assertEquals( 1, $queue->getSize(), "Queue size is correct ($desc)" );
86 $queue->flushCaches();
88 $this->assertEquals( 1, $queue->getAcquiredCount(), "Active job count ($desc)" );
90 $this->assertEquals( 0, $queue->getAcquiredCount(), "Active job count ($desc)" );
93 $job2 = $queue->pop();
94 $this->assertTrue( $queue->isEmpty(), "Queue is empty ($desc)" );
95 $this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
97 $queue->flushCaches();
99 $this->assertEquals( 2, $queue->getAcquiredCount(), "Active job count ($desc)" );
101 $this->assertEquals( 0, $queue->getAcquiredCount(), "Active job count ($desc)" );
104 $queue->ack( $job1 );
106 $queue->flushCaches();
108 $this->assertEquals( 1, $queue->getAcquiredCount(), "Active job count ($desc)" );
110 $this->assertEquals( 0, $queue->getAcquiredCount(), "Active job count ($desc)" );
113 $queue->ack( $job2 );
115 $queue->flushCaches();
116 $this->assertEquals( 0, $queue->getAcquiredCount(), "Active job count ($desc)" );
120 * @dataProvider provider_queueLists
122 function testBasicDeduplication( $queue, $order, $recycles, $desc ) {
123 $queue = $this->$queue;
125 $this->assertTrue( $queue->isEmpty(), "Queue is empty ($desc)" );
127 $queue->flushCaches();
128 $this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
129 $this->assertEquals( 0, $queue->getAcquiredCount(), "Queue is empty ($desc)" );
131 $this->assertTrue( $queue->batchPush(
132 array( $this->newDedupedJob(), $this->newDedupedJob(), $this->newDedupedJob() ) ),
133 "Push worked ($desc)" );
135 $this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
137 $queue->flushCaches();
138 $this->assertEquals( 1, $queue->getSize(), "Queue size is correct ($desc)" );
139 $this->assertEquals( 0, $queue->getAcquiredCount(), "No jobs active ($desc)" );
141 $this->assertTrue( $queue->batchPush(
142 array( $this->newDedupedJob(), $this->newDedupedJob(), $this->newDedupedJob() ) ),
143 "Push worked ($desc)" );
145 $this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
147 $queue->flushCaches();
148 $this->assertEquals( 1, $queue->getSize(), "Queue size is correct ($desc)" );
149 $this->assertEquals( 0, $queue->getAcquiredCount(), "No jobs active ($desc)" );
151 $job1 = $queue->pop();
152 $this->assertTrue( $queue->isEmpty(), "Queue is empty ($desc)" );
154 $queue->flushCaches();
155 $this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
157 $this->assertEquals( 1, $queue->getAcquiredCount(), "Active job count ($desc)" );
159 $this->assertEquals( 0, $queue->getAcquiredCount(), "Active job count ($desc)" );
162 $queue->ack( $job1 );
164 $queue->flushCaches();
165 $this->assertEquals( 0, $queue->getAcquiredCount(), "Active job count ($desc)" );
169 * @dataProvider provider_queueLists
171 function testRootDeduplication( $queue, $order, $recycles, $desc ) {
172 $queue = $this->$queue;
174 $this->assertTrue( $queue->isEmpty(), "Queue is empty ($desc)" );
176 $queue->flushCaches();
177 $this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
178 $this->assertEquals( 0, $queue->getAcquiredCount(), "Queue is empty ($desc)" );
180 $id = wfRandomString( 32 );
181 $root1 = Job
::newRootJobParams( "nulljobspam:$id" ); // task ID/timestamp
182 for ( $i = 0; $i < 5; ++
$i ) {
183 $this->assertTrue( $queue->push( $this->newJob( 0, $root1 ) ), "Push worked ($desc)" );
185 $queue->deduplicateRootJob( $this->newJob( 0, $root1 ) );
186 sleep( 1 ); // roo job timestamp will increase
187 $root2 = Job
::newRootJobParams( "nulljobspam:$id" ); // task ID/timestamp
188 $this->assertNotEquals( $root1['rootJobTimestamp'], $root2['rootJobTimestamp'],
189 "Root job signatures have different timestamps." );
190 for ( $i = 0; $i < 5; ++
$i ) {
191 $this->assertTrue( $queue->push( $this->newJob( 0, $root2 ) ), "Push worked ($desc)" );
193 $queue->deduplicateRootJob( $this->newJob( 0, $root2 ) );
195 $this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
197 $queue->flushCaches();
198 $this->assertEquals( 10, $queue->getSize(), "Queue size is correct ($desc)" );
199 $this->assertEquals( 0, $queue->getAcquiredCount(), "No jobs active ($desc)" );
204 $job = $queue->pop();
209 if ( $job instanceof DuplicateJob
) {
214 $this->assertEquals( 10, count( $jobs ), "Correct number of jobs popped ($desc)" );
215 $this->assertEquals( 5, $dupcount, "Correct number of duplicate jobs popped ($desc)" );
219 * @dataProvider provider_fifoQueueLists
221 function testJobOrder( $queue, $recycles, $desc ) {
222 $queue = $this->$queue;
224 $this->assertTrue( $queue->isEmpty(), "Queue is empty ($desc)" );
226 $queue->flushCaches();
227 $this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
228 $this->assertEquals( 0, $queue->getAcquiredCount(), "Queue is empty ($desc)" );
230 for ( $i = 0; $i < 10; ++
$i ) {
231 $this->assertTrue( $queue->push( $this->newJob( $i ) ), "Push worked ($desc)" );
234 for ( $i = 0; $i < 10; ++
$i ) {
235 $job = $queue->pop();
236 $this->assertTrue( $job instanceof Job
, "Jobs popped from queue ($desc)" );
237 $params = $job->getParams();
238 $this->assertEquals( $i, $params['i'], "Job popped from queue is FIFO ($desc)" );
242 $this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
244 $queue->flushCaches();
245 $this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
246 $this->assertEquals( 0, $queue->getAcquiredCount(), "No jobs active ($desc)" );
249 function provider_queueLists() {
251 array( 'queueRand', 'rand', false, 'Random queue without ack()' ),
252 array( 'queueRandTTL', 'rand', true, 'Random queue with ack()' ),
253 array( 'queueFifo', 'fifo', false, 'Ordered queue without ack()' ),
254 array( 'queueFifoTTL', 'fifo', true, 'Ordered queue with ack()' )
258 function provider_fifoQueueLists() {
260 array( 'queueFifo', false, 'Ordered queue without ack()' ),
261 array( 'queueFifoTTL', true, 'Ordered queue with ack()' )
265 function newJob( $i = 0, $rootJob = array() ) {
266 return new NullJob( Title
::newMainPage(),
267 array( 'lives' => 0, 'usleep' => 0, 'removeDuplicates' => 0, 'i' => $i ) +
$rootJob );
270 function newDedupedJob( $i = 0, $rootJob = array() ) {
271 return new NullJob( Title
::newMainPage(),
272 array( 'lives' => 0, 'usleep' => 0, 'removeDuplicates' => 1, 'i' => $i ) +
$rootJob );