Projet

Général

Profil

Paste
Télécharger (28,9 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / cas / cas.test @ e9f59589

1
<?php
2

    
3
/**
4
 * @file
5
 * Tests for cas.module.
6
 */
7

    
8
class CasTestHelper extends DrupalWebTestCase {
9
  protected $admin_user;
10

    
11
  /**
12
   * Helper class for CAS tests.
13
   *
14
   * Creates an administrative user and downloads phpCAS.
15
   */
16
  function setUp() {
17
    // Install modules needed for this test. This could have been passed in as
18
    // either a single array argument or a variable number of string arguments.
19
    // @todo Remove this compatibility layer in Drupal 8, and only accept
20
    // $modules as a single array argument.
21
    $modules = func_get_args();
22
    if (isset($modules[0]) && is_array($modules[0])) {
23
      $modules = $modules[0];
24
    }
25

    
26
    // cas_test requires the CAS Server module.
27
    $modules = array_merge(array('cas', 'cas_test', 'cas_server'), $modules);
28
    parent::setUp($modules);
29

    
30
    // Tests will fail unless clean URLs are enabled, due to an incompatibility
31
    // in phpCAS.
32
    variable_set('clean_url', TRUE);
33

    
34
    // Create admin user.
35
    $this->admin_user = $this->drupalCreateUser(array('administer users', 'administer cas'));
36

    
37
    // Download and extract in PHPCAS.
38
    $this->downloadExtractPhpCas('1.3.2');
39
  }
40

    
41
  /**
42
   * Download and extract phpCAS.
43
   *
44
   * Sets the 'cas_library_dir' variable to the directory where phpCAS
45
   * is downloaded.
46
   *
47
   * @param $version
48
   *   The phpCAS version number to download and extract.
49
   */
50
  function downloadExtractPhpCas($version) {
51
    // Find the most URL of the most recent phpCAS version.
52
    $directory = 'CAS-' . $version;
53
    $filename = 'CAS-' . $version . '.tgz';
54
    $url = 'http://downloads.jasig.org/cas-clients/php/' . $version . '/' . $filename;
55

    
56
    // Avoid downloading the file dozens of times
57
    $simpletest_cache = $this->originalFileDirectory . '/simpletest/cas';
58
    if (!file_exists($simpletest_cache)) {
59
      mkdir($simpletest_cache);
60
    }
61

    
62
    // Local archive name.
63
    $local_archive = $simpletest_cache . '/' . $filename;
64
    $cas_library_dir = $simpletest_cache . '/' . $directory;
65

    
66
    // Begin single threaded code.
67
    if (function_exists('sem_get')) {
68
      $semaphore = sem_get(ftok(__FILE__, 1));
69
      sem_acquire($semaphore);
70
    }
71

    
72
    // Download and extact the archive, but only in one thread.
73
    if (!file_exists($local_archive)) {
74
      $local_archive = system_retrieve_file($url, $local_archive, FALSE, FILE_EXISTS_REPLACE);
75
    }
76
    if (!file_exists($cas_library_dir)) {
77
      // Extract the files.
78
      $archiver = archiver_get_archiver($local_archive);
79
      $archiver->extract($simpletest_cache);
80
    }
81
    if (function_exists('sem_get')) {
82
      sem_release($semaphore);
83
    }
84
    // End single threaded code.
85

    
86
    // Verify that files were successfully extracted.
87
    $this->assertTrue(file_exists($cas_library_dir . '/CAS.php'), t('CAS.php found in @cas_library_dir.', array('@cas_library_dir' => $cas_library_dir)));
88

    
89
    // Set the CAS library directory.
90
    variable_set('cas_library_dir', $cas_library_dir);
91
  }
92

    
93
  /**
94
   * Create a CAS user with the specified username.
95
   *
96
   * @param $cas_name
97
   *   The CAS username. If omitted, a CAS username will be automatically
98
   *   generated.
99
   * @param $permissions
100
   *   An array of permissions to assign to the created user.
101
   *
102
   * @return
103
   *   A user account object. The CAS username is present in the cas_name
104
   *   field.
105
   */
106
  function casCreateUser($cas_name = NULL, $permissions = array('access comments', 'access content', 'post comments', 'skip comment approval')) {
107
    // Create user.
108
    $account = $this->drupalCreateUser($permissions);
109
    $pass_raw = $account->pass_raw;
110

    
111
    // Add CAS username.
112
    if (empty($cas_name)) {
113
      $cas_name = $this->randomName();
114
    }
115
    $edit['cas_name'] = $cas_name;
116
    $account = user_save($account, $edit);
117

    
118
    // Restore password.
119
    $account->pass_raw = $pass_raw;
120
    return $account;
121
  }
122

    
123
  /**
124
   * Log in a CAS user with the internal browser.
125
   *
126
   * @param $account
127
   *   A user object with a valid CAS username field, or the CAS username as a
128
   *   string.
129
   * @param $attributes
130
   *   Additional attributes for the CAS user.
131
   */
132
  function casLogin($account, $attributes = array()) {
133
    if ($this->loggedInUser) {
134
      $this->drupalLogout();
135
    }
136

    
137
    // Log in the user.
138
    $cas_name = $this->setCasUser($account, $attributes);
139
    $this->drupalGet('cas');
140

    
141
    $pass = $this->assertLink(t('Log out'), 0, t('CAS user %cas_name successfully logged in.', array('%cas_name' => $cas_name)), t('User login'));
142
    if ($pass) {
143
      $this->loggedInUser = cas_user_load_by_name($cas_name, TRUE, TRUE);
144
    }
145
  }
146

    
147
  /**
148
   * Set the CAS username and attributes for the next CAS login request.
149
   *
150
   * @param $account
151
   *   A user object with a valid CAS username field, or the CAS username as a
152
   *   string.
153
   * @param $attributes
154
   *   Additional attributes for the CAS user.
155
   *
156
   * @return
157
   *   The CAS username.
158
   */
159
  function setCasUser($account, $attributes = array()) {
160
    $cas_name = is_object($account) ? $account->cas_name : $account;
161
    $cas_user = array('name' => $cas_name, 'attributes' => $attributes);
162
    variable_set('cas_test_cas_user', $cas_user);
163
    return $cas_name;
164
  }
165

    
166
  /**
167
   * Clear the CAS username and attributes for the next CAS login request.
168
   */
169
  function clearCasUser() {
170
    variable_del('cas_test_cas_user');
171
  }
172

    
173
  /**
174
   * Assert that the user has logged in.
175
   *
176
   * @return
177
   *  TRUE if the assertion succeeded, FALSE otherwise.
178
   */
179
  function assertLoggedIn($account) {
180
    $pass = $this->assertLink(t('Log out'), 0, t('CAS user %cas_name successfully logged in.', array('%cas_name' => $account->cas_name)), t('User login'));
181
    if ($pass) {
182
      $this->loggedInUser = $account;
183
    }
184
    return $pass;
185
  }
186

    
187
  /**
188
   * Assert that the user has been logged out.
189
   *
190
   * @return
191
   *  TRUE if the assertion succeeded, FALSE otherwise.
192
   */
193
  function assertLoggedOut() {
194
    $this->drupalGet('user');
195
    $pass = $this->assertField('name', t('Username field found.'), t('Logout'));
196
    $pass = $pass && $this->assertField('pass', t('Password field found.'), t('Logout'));
197
    if ($pass) {
198
      $this->loggedInUser = FALSE;
199
    }
200
    return $pass;
201
  }
202

    
203
  /**
204
   * Assert the value of the token.
205
   *
206
   * @param $token
207
   *   A token to evaluate for the current CAS user.
208
   * @param $value
209
   *   The expected value after the token is evaluated.
210
   * @param $message
211
   *   The message to display along with the assertion.
212
   *
213
   * @return
214
   *  TRUE if the assertion succeeded, FALSE otherwise.
215
   */
216
  function assertToken($token, $value, $message = '') {
217
    $options = array(
218
      'query' => array(
219
        'token' => $token,
220
        'name' => $this->loggedInUser->cas_name,
221
      ),
222
    );
223
    $path = 'cas_test/token';
224
    $out = $this->drupalGet($path, $options);
225
    return $this->assertEqual($out, $value, $message, 'Token');
226
  }
227

    
228
}
229

    
230
class CasUserAdminTestCase extends CasTestHelper {
231

    
232
  public static function getInfo() {
233
    return array(
234
      'name' => 'User administration',
235
      'description' => 'Test CAS user administration.',
236
      'group' => 'Central Authentication Service'
237
    );
238
  }
239

    
240
  /**
241
   * Registers, modifies, and deletes a CAS user using User API hooks.
242
   */
243
  function testCASUserHooks() {
244
    // Create a test account.
245
    $account = $this->drupalCreateUser();
246
    $uid = $account->uid;
247

    
248
    // Add a CAS username.
249
    $cas_name = $this->randomName();
250
    $edit = array('cas_name' => $cas_name);
251
    $account = user_save($account, $edit);
252
    $this->assertEqual($cas_name, $account->cas_name, t('CAS username %cas_name successfully created.', array('%cas_name' => $cas_name)));
253

    
254
    // Reload the account and ensure the CAS name is still present.
255
    $account = user_load($uid);
256
    $this->assertEqual($cas_name, $account->cas_name, t('CAS username %cas_name successfully saved.', array('%cas_name' => $cas_name)));
257

    
258
    // Load the account by the CAS username.
259
    $account = cas_user_load_by_name($cas_name);
260
    $this->assertEqual($uid, $account->uid, t('Loaded the correct account with CAS username %cas_name.', array('%cas_name' => $cas_name)));
261

    
262
    // Change the CAS username.
263
    $cas_new_name = $this->randomName();
264
    $account = user_load($uid);
265
    $edit = array('cas_name' => $cas_new_name);
266
    user_save($account, $edit);
267
    $account = user_load($uid);
268
    $this->assertEqual($cas_new_name, $account->cas_name, t('CAS username %cas_name successfully updated.', array('%cas_name' => $cas_new_name)));
269
    $this->assertEqual(count($account->cas_names), 1, t('Only one CAS username is present.'));
270
    $account = cas_user_load_by_name($cas_name);
271
    $this->assertFalse($account, t('Could not load account using old CAS username.'));
272

    
273
    // Remove the CAS username.
274
    $account = user_load($uid);
275
    $edit = array('cas_name' => NULL);
276
    user_save($account, $edit);
277
    $account = user_load($uid);
278
    $this->assertFalse($account->cas_name, t('CAS username successfully deleted.'));
279
    $this->assertEqual(count($account->cas_names), 0, t('No CAS usernames are present.'));
280

    
281
    // Attempt to load by a non-existant CAS username.
282
    $account = cas_user_load_by_name($cas_new_name);
283
    $this->assertFalse($account, t('Could not load account with non-existent CAS username.'));
284

    
285
    // Verify that all CAS usernames have been removed from {cas_user}.
286
    $cas_uid_count = db_select('cas_user')
287
      ->condition('cas_name', array($cas_name, $cas_new_name), 'IN')
288
      ->countQuery()
289
      ->execute()
290
      ->fetchField();
291
    $this->assertEqual($cas_uid_count, 0, t('CAS usernames successfully removed from {cas_user}.'));
292
  }
293
  /**
294
   * Tests adding a user with a CAS username in the administrative interface.
295
   */
296
  function testUserAdd() {
297
    $this->drupalLogin($this->admin_user);
298

    
299
    // Register a user with a CAS username.
300
    $cas_name = $this->randomName();
301
    $edit = array(
302
      'name' => $this->randomName(),
303
      'mail' => $this->randomName() . '@example.com',
304
      'cas_name' => $cas_name,
305
      'pass[pass1]' => $pass = $this->randomString(),
306
      'pass[pass2]' => $pass,
307
      'notify' => FALSE,
308
    );
309
    $this->drupalPost('admin/people/create', $edit, t('Create new account'));
310
    $this->assertText(t('Created a new user account for @name. No e-mail has been sent.', array('@name' => $edit['name'])), 'User created');
311

    
312
    $this->drupalGet('admin/people');
313
    $this->assertText($edit['name'], 'User found in list of users');
314
    $this->assertText($edit['cas_name'], 'CAS username found in list of users');
315

    
316
    // Verify that duplicate CAS usernames are not allowed.
317
    $edit = array(
318
      'name' => $this->randomName(),
319
      'mail' => $this->randomName() . '@example.com',
320
      'cas_name' => $cas_name,
321
      'pass[pass1]' => $pass = $this->randomString(),
322
      'pass[pass2]' => $pass,
323
      'notify' => FALSE,
324
    );
325
    $this->drupalPost('admin/people/create', $edit, t('Create new account'));
326
    $this->assertText(t('The CAS username is already in use on this site.'), 'CAS username already in use.');
327
  }
328

    
329
  /**
330
   * Tests adding a CAS user in the administrative interface.
331
   */
332
  function testCasUserAdd() {
333
    $this->drupalLogin($this->admin_user);
334

    
335
    // Add 3 CAS users.
336
    $edit = array();
337
    for ($i = 0; $i < 3; $i++) {
338
      $cas_names[] = $this->randomName();
339
    }
340
    $edit['cas_name'] = implode("\n", $cas_names);
341
    $this->drupalPost('admin/people/cas/create', $edit, t('Create new account(s)'));
342
    $this->assertText(t('The following 3 CAS usernames were created: @cas_names', array('@cas_names' => implode(', ', $cas_names))), 'Users created');
343

    
344
    // Verify the users show up in the list of all users.
345
    $this->drupalGet('admin/people');
346
    foreach ($cas_names as $cas_name) {
347
      $this->assertNoUniqueText($cas_name, 'User and CAS username found in list of users');
348
    }
349

    
350
    // Attempt to add one of the users again and see that it fails.
351
    $edit['cas_name'] = $cas_names[0];
352
    $this->drupalPost('admin/people/cas/create', $edit, t('Create new account(s)'));
353
    $this->assertText(t('The CAS username is already in use on this site.'), 'CAS username already in use.');
354
  }
355
}
356

    
357
/**
358
 * Test case to test user editing behavior.
359
 */
360
class CasUserTestCase extends CasTestHelper {
361

    
362
  public static function getInfo() {
363
    return array(
364
      'name' => 'User behavior',
365
      'description' => 'Test CAS user behavior, including auto-registration and user editing.',
366
      'group' => 'Central Authentication Service',
367
    );
368
  }
369

    
370
  /**
371
   * Tests automatically registering a user on login.
372
   */
373
  function testCasAutoRegister() {
374
    $cas_name = $this->randomName();
375
    $this->setCasUser($cas_name);
376

    
377
    // Test that the user is not automatically registered.
378
    variable_set('cas_user_register', FALSE);
379
    $this->drupalGet('cas');
380
    $this->assertRaw(t('No account found for %cas_name.', array('%cas_name' => $cas_name)));
381

    
382
    // Ensure that the login result is not cached.
383
    $cas_name = $this->randomName();
384
    $this->setCasUser($cas_name);
385
    $this->drupalGet('cas');
386
    $this->assertRaw(t('No account found for %cas_name.', array('%cas_name' => $cas_name)));
387

    
388
    // Test that the user is automatically registered.
389
    variable_set('cas_user_register', TRUE);
390
    $this->drupalGet('cas');
391
    $this->loggedInUser = cas_user_load_by_name($cas_name, TRUE);
392
    $this->assertRaw(t('Logged in via CAS as %cas_username.', array('%cas_username' => $cas_name)));
393
    $this->drupalLogout();
394

    
395
    // Create a new user.
396
    $user2 = $this->drupalCreateUser();
397
    $cas_name = $user2->name;
398
    $this->setCasUser($cas_name);
399

    
400
    // Test that CAS does not hijack an existing username.
401
    $this->drupalGet('cas');
402
    $this->assertRaw(t('A new account could not be created for %cas_name. The username is already in use on this site.', array('%cas_name' => $cas_name)));
403
  }
404

    
405
  function testUserEdit() {
406
    $cas_name = $this->randomName();
407
    $account = $this->casCreateUser($cas_name, array('change own username'));
408

    
409
    $this->casLogin($cas_name);
410

    
411
    // Standard user page.
412
    variable_set('cas_hide_email', FALSE);
413
    variable_set('cas_hide_password', FALSE);
414
    $this->drupalGet("user/$account->uid/edit");
415
    $this->assertField('mail', 'E-mail field is present.');
416
    $this->assertField('current_pass', 'Current password field is present.');
417
    $this->assertField('pass[pass1]', 'Existing password field 1 is present.');
418
    $this->assertField('pass[pass2]', 'Existing password field 2 is present.');
419
    $edit = array(
420
      'mail' => $mail = $this->randomName() . '@example.com',
421
      'current_pass' => $account->pass_raw,
422
    );
423
    $this->drupalPost("user/$account->uid/edit", $edit, t('Save'));
424
    $this->assertFieldByName('mail', $mail);
425

    
426
    // Hide the password, ensure edits can be made without providing
427
    // the current password.
428
    variable_set('cas_hide_password', TRUE);
429
    $this->drupalGet("user/$account->uid/edit");
430
    $this->assertNoField('current_pass', 'Current password field is not present.');
431
    $this->assertNoField('pass[pass1]', 'Existing password field 1 is not present.');
432
    $this->assertNoField('pass[pass2]', 'Existing password field 2 is not present.');
433
    $edit = array(
434
      'mail' => $mail = $this->randomName() . '@example.com',
435
    );
436
    $this->drupalPost("user/$account->uid/edit", $edit, t('Save'));
437
    $this->assertFieldByName('mail', $mail);
438

    
439
    // Hide the e-mail field as well, ensure that it is not visible.
440
    variable_set('cas_hide_email', TRUE);
441
    $this->drupalGet("user/$account->uid/edit");
442
    $this->assertNoField('mail', 'E-mail field is not present.');
443
  }
444

    
445
  function testNameToken() {
446
    $account = $this->casCreateUser();
447
    $this->casLogin($account);
448

    
449
    $this->assertToken('[cas:name]', $account->cas_name);
450
  }
451

    
452
  function testCaseInsensitiveLogin() {
453
    $account = $this->casCreateUser();
454
    $this->casLogin(strtoupper($account->cas_name));
455
    $this->assertLoggedIn($account);
456
  }
457

    
458
}
459

    
460
/**
461
 * Test case to test user logout behavior.
462
 */
463
class CasLogoutRedirectionTestCase extends CasTestHelper {
464

    
465
  public static function getInfo() {
466
    return array(
467
      'name' => 'Logout redirection',
468
      'description' => 'Test CAS user logout redirection.',
469
      'group' => 'Central Authentication Service',
470
    );
471
  }
472

    
473
  /**
474
   * Test redirection on user logout.
475
   */
476
  function testLogoutRedirection() {
477
    $account = $this->casCreateUser();
478

    
479
    $this->casLogin($account);
480
    $this->drupalGet('caslogout');
481
    $this->assertText('Logged out. No redirection provided.');
482
    $this->assertLoggedOut();
483

    
484
    // Verify the destination parameter may be passed on logout, i.e.,
485
    // caslogout?destination=node
486
    $destination = 'node';
487
    $this->casLogin($account);
488
    $this->drupalGet('caslogout', array('query' => array('destination' => $destination)));
489
    $this->assertText(t('Logged out. Continue to @url.', array('@url' => url($destination, array('absolute' => TRUE)))));
490
    $this->assertLoggedOut();
491

    
492
    // Verify that remote destination parameters are not allowed.
493
    $destination = 'http://example.com/?query=yes#fragment';
494
    $this->casLogin($account);
495
    $this->drupalGet('caslogout', array('query' => array('destination' => $destination)));
496
    $this->assertText(t('Logged out. No redirection provided.'));
497
    $this->assertLoggedOut();
498

    
499
    // Verify 'cas_logout_destination' works for a variety of destinations,
500
    // including remote destinations.
501
    $destinations = array('<front>', 'http://example.com/?query=yes#fragment', 'node/1');
502
    foreach ($destinations as $destination) {
503
      variable_set('cas_logout_destination', $destination);
504
      $this->casLogin($account);
505
      $this->drupalGet('caslogout');
506
      $this->assertText(t('Logged out. Continue to @url.', array('@url' => url($destination, array('absolute' => TRUE)))));
507
      $this->assertLoggedOut();
508
    }
509

    
510
    // Verify 'cas_logout_destination' can be overwritten by passing the
511
    // destination query string.
512
    variable_set('cas_logout_destination', 'http://example.com/');
513
    $destination = 'node/1';
514
    $this->casLogin($account);
515
    $this->drupalGet('caslogout', array('query' => array('destination' => $destination)));
516
    $this->assertText(t('Logged out. Continue to @url.', array('@url' => url($destination, array('absolute' => TRUE)))));
517
    $this->assertLoggedOut();
518
  }
519
}
520

    
521
/**
522
 * Test case to test user login behavior.
523
 */
524
class CasLoginRedirectionTestCase extends CasTestHelper {
525

    
526
  public static function getInfo() {
527
    return array(
528
      'name' => 'Login redirection',
529
      'description' => 'Test CAS user login redirection.',
530
      'group' => 'Central Authentication Service',
531
    );
532
  }
533

    
534
  /**
535
   * Verify login redirection for an existing user.
536
   */
537
  function testExistingUserLoginRedirection() {
538
    $node1 = $this->drupalCreateNode();
539
    $node2 = $this->drupalCreateNode();
540
    $node3 = $this->drupalCreateNode();
541

    
542
    // Create a CAS user.
543
    $account = $this->casCreateUser();
544
    $cas_name = $account->cas_name;
545
    $this->setCasUser($cas_name);
546

    
547
    // Test going to 'cas'
548
    $this->drupalGet('cas');
549
    $this->assertLoggedIn($account);
550
    $this->assertUrl('');
551
    $this->drupalLogout();
552

    
553
    // Test going to 'cas?destination=node/$node1->nid'
554
    $destination = "node/$node1->nid";
555
    $this->drupalGet('cas', array('query' => array('destination' => $destination)));
556
    $this->assertLoggedIn($account);
557
    $this->assertUrl($destination);
558
    $this->drupalLogout();
559

    
560
    // Use the login block on $node2.
561
    $destination = "node/$node2->nid";
562
    variable_set('cas_login_form', CAS_ADD_LINK);
563
    $edit = array('cas_identifier' => TRUE);
564
    $this->drupalPost($destination, $edit, t('Log in'));
565
    $this->assertLoggedIn($account);
566
    $this->assertUrl($destination);
567
    $this->drupalLogout();
568

    
569
    // Use the regular login page, without a destination.
570
    $edit = array('cas_identifier' => TRUE);
571
    $this->drupalPost('user/login', $edit, t('Log in'));
572
    $this->assertLoggedIn($account);
573
    $this->assertUrl('user');
574
    $this->drupalLogout();
575

    
576
    // Use the regular login page, with a destination.
577
    $destination = "node/$node3->nid";
578
    $edit = array('cas_identifier' => TRUE);
579
    $this->drupalPost('user/login', $edit, t('Log in'), array('query' => array('destination' => $destination)));
580
    $this->assertLoggedIn($account);
581
    $this->assertUrl($destination);
582
    $this->drupalLogout();
583

    
584
    // External destinations are not allowed.
585
    $destination = '';
586
    $this->drupalGet('cas', array('query' => array('destination' => 'http://example.com/node/3')));
587
    $this->assertLoggedIn($account);
588
    $this->assertUrl($destination);
589
    $this->drupalLogout();
590
  }
591

    
592
  /**
593
   * Verify login redirection for a new user.
594
   */
595
  function testNewUserLoginRedirection() {
596
    // Initial login without a destination goes to front page.
597
    $cas_name = $this->randomName();
598
    $this->casLogin($cas_name);
599
    $this->assertUrl('');
600
    $this->drupalLogout();
601

    
602
    // Initial login with redirection goes to specified destination.
603
    $node = $this->drupalCreateNode();
604
    variable_set('cas_first_login_destination', "node/$node->nid");
605
    $cas_name = $this->randomName();
606
    $account = $this->casLogin($cas_name);
607
    $this->assertUrl("node/$node->nid");
608
    $this->drupalLogout();
609

    
610
    // The second login should not be redirected.
611
    $this->casLogin($cas_name);
612
    $this->assertUrl('');
613
    $this->drupalLogout();
614

    
615
    // Initial login with a admin-created account goes to the specified
616
    // destination.
617
    $account = $this->casCreateUser();
618
    $this->casLogin($account);
619
    $this->assertUrl("node/$node->nid");
620
    $this->drupalLogout();
621

    
622
    // The second login should not be redirected.
623
    $this->casLogin($account);
624
    $this->assertUrl('');
625
    $this->drupalLogout();
626
  }
627
}
628

    
629
/**
630
 * Test CAS Single Sign-Out.
631
 */
632
class CasSingleSignOutTestCase extends CasTestHelper {
633

    
634
  public static function getInfo() {
635
    return array(
636
      'name' => 'Single Sign-Out',
637
      'description' => 'Test CAS Single Sign-Out.',
638
      'group' => 'Central Authentication Service',
639
    );
640
  }
641

    
642
  function testSingleSignOut() {
643
    // Create a user, and log in.
644
    $cas_name = $this->randomName();
645
    $account = $this->casCreateUser($cas_name);
646
    $this->casLogin($account);
647

    
648
    cas_test_single_sign_out($cas_name);
649
    $this->assertLoggedOut();
650

    
651
    // @todo: Add additional tests for other methods of logging in (especially
652
    //   methods coming from cas_pages).
653
  }
654

    
655
  function testSingleSignOutDoubleEncode() {
656
    // Create a user, and log in.
657
    $cas_name = $this->randomName();
658
    $account = $this->casCreateUser($cas_name);
659
    $this->casLogin($account);
660

    
661
    cas_test_single_sign_out($cas_name, TRUE);
662
    $this->assertLoggedOut();
663

    
664
    // @todo: Add additional tests for other methods of logging in (especially
665
    //   methods coming from cas_pages).
666
  }
667
}
668

    
669
/**
670
 * Test case for CAS gateway feature.
671
 */
672
class CasGatewayTestCase extends CasTestHelper {
673

    
674
  public static function getInfo() {
675
    return array(
676
      'name' => 'CAS Gateway',
677
      'description' => 'Test CAS Gateway ("Check to see if user is already logged in") feature.',
678
      'group' => 'Central Authentication Service',
679
    );
680
  }
681

    
682
  function setUp() {
683
    parent::setUp();
684
  }
685

    
686
  /**
687
   * Test the CAS Gateway functionality of the user is not logged in.
688
   */
689
  function testCasGatewayLoggedOut() {
690
    $node1 = $this->drupalCreateNode();
691

    
692
    variable_set('cas_check_frequency', CAS_CHECK_ONCE);
693
    $this->drupalGet('');
694
    $this->assertTrue($this->redirect_count == 2, 'Polled CAS server on first request.');
695
    $this->drupalGet('');
696
    $this->assertEqual($this->redirect_count, 0, 'Did not poll CAS server on second request.');
697
    $this->drupalGet('node/' . $node1->nid);
698
    $this->assertEqual($this->redirect_count, 0, 'Did not poll CAS server on third request.');
699
    $this->assertFalse($this->loggedInUser);
700

    
701
    variable_set('cas_check_frequency', CAS_CHECK_ALWAYS);
702
    $this->drupalGet('');
703
    $this->assertTrue($this->redirect_count == 2, 'Polled CAS server on first request');
704
    $this->drupalGet('');
705
    $this->assertTrue($this->redirect_count == 2, 'Polled CAS server on second request');
706
    $this->drupalGet('node/' . $node1->nid);
707
    $this->assertEqual($this->redirect_count == 2, 'Polled CAS server on third request');
708
    $this->assertFalse($this->loggedInUser);
709
  }
710

    
711
  /**
712
   * Test the CAS Gateway functionality of the user is logged in.
713
   */
714
  function testCasGatewayLoggedIn() {
715
    // Create a user.
716
    $cas_name = $this->randomName();
717
    $account = $this->casCreateUser($cas_name);
718
    $this->setCasUser($cas_name);
719

    
720
    variable_set('cas_check_frequency', CAS_CHECK_ONCE);
721
    $this->drupalGet('');
722
    $this->assertLoggedIn($account);
723
    // Logging out should immediately log a user back in
724
    $this->drupalGet('user/logout');
725
    $this->assertLoggedIn($account);
726

    
727
    variable_set('cas_check_frequency', CAS_CHECK_ALWAYS);
728
    $this->drupalGet('');
729
    $this->assertLoggedIn($account);
730
    // Logging out should immediately log a user back in
731
    $this->drupalGet('user/logout');
732
    $this->assertLoggedIn($account);
733
  }
734
}
735

    
736
/**
737
 * Test case for CAS force login feature.
738
 */
739
class CasRequiredLoginTestCase extends CasTestHelper {
740

    
741
  public static function getInfo() {
742
    return array(
743
      'name' => 'Required Login',
744
      'description' => 'Test CAS required login redirection.',
745
      'group' => 'Central Authentication Service',
746
    );
747
  }
748

    
749
  /**
750
   * Test redirection forced by cas_access and cas_pages variables.
751
   */
752
  function testCasPages() {
753
    $node1 = $this->drupalCreateNode();
754
    $node2 = $this->drupalCreateNode();
755
    $account = $this->casCreateUser();
756
    $this->setCasUser($account);
757

    
758
    $this->drupalGet("node/$node2->nid");
759

    
760
    // Enable required login for $node.
761
    variable_set('cas_access', 0);
762
    variable_set('cas_pages', "node/$node1->nid\nnode/$node2->nid");
763

    
764
    // Visit the node and verify we are logged in.
765
    $this->drupalGet("node/$node2->nid");
766
    $this->assertLoggedIn($account);
767
    $this->assertUrl("node/$node2->nid");
768
    $this->drupalLogout();
769

    
770
    // Invert the access restrictions. Verify we can get the access the node
771
    // without restriction.
772
    variable_set('cas_access', 1);
773
    $this->drupalGet("node/$node1->nid");
774
    $this->assertField('name', t('Username field found.'), t('Logout'));
775
    $this->assertField('pass', t('Password field found.'), t('Logout'));
776

    
777
    // Verify that accessing any other page redirects to the login page.
778
    $this->clearCasUser();
779
    $this->drupalGet('node');
780
    $this->assertText('No CAS name provided.');
781
  }
782

    
783
  /**
784
   * Test redirection prevented by cas_exclude.
785
   */
786
  function testCasExclude() {
787
    $node = $this->drupalCreateNode();
788
    $account = $this->casCreateUser();
789
    $this->setCasUser($account);
790

    
791
    variable_set('cas_check_frequency', CAS_CHECK_ONCE);
792
    variable_set('cas_exclude', "node/$node->nid");
793

    
794
    // Visit an excluded page and ensure we did not try to log in.
795
    $this->drupalGet("node/$node->nid");
796
    $this->assertField('name', t('Username field found.'), t('Logout'));
797
    $this->assertField('pass', t('Password field found.'), t('Logout'));
798

    
799
    // Visit another page and ensure we logged in.
800
    $this->drupalGet('node');
801
    $this->assertLoggedIn($account);
802
    $this->assertUrl('node');
803
  }
804
}
805

    
806
/**
807
 * Tests the visibility and functionality of the CAS login block.
808
 */
809
class CasLoginBlockTestCase extends CasTestHelper {
810
  public static function getInfo() {
811
    return array(
812
      'name' => 'CAS login block',
813
      'description' => 'Tests the CAS login block.',
814
      'group' => 'Central Authentication Service',
815
    );
816
  }
817

    
818
  function setUp() {
819
    parent::setUp();
820

    
821
    // Enable the CAS login block.
822
    $admin_user = $this->drupalCreateUser(array('administer blocks'));
823
    $this->drupalLogin($admin_user);
824
    $edit = array(
825
      'blocks[user_login][region]' => '-1',
826
      'blocks[cas_login][region]' => 'sidebar_first',
827
    );
828
    $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
829
    $this->drupalLogout();
830
  }
831

    
832
  /**
833
   * Asserts that the CAS login block is shown or not shown.
834
   *
835
   * @param $visible
836
   *   Whether or not the CAS login block is expected to be shown.
837
   *
838
   * @return
839
   *  TRUE if the assertion succeeded, FALSE otherwise.
840
   */
841
  function assertCasLoginBlock($visible) {
842
    $xpath = '//div[@id=block-cas-0]/*';
843
    $xpath = $this->buildXPathQuery('//div[@id=:id]/*', array(':id' => 'block-cas-login'));
844
    if ($visible) {
845
      return $this->assertFieldByXPath($xpath, NULL, t('CAS login block found.'));
846
    }
847
    else {
848
      return $this->assertNoFieldByXPath($xpath, NULL, t('CAS login block not found.'));
849
    }
850
  }
851

    
852
  /**
853
   * Tests the visibility and functionality of the CAS login block.
854
   */
855
  function testCasLoginBlock() {
856
    $account = $this->casCreateUser();
857
    $this->setCasUser($account);
858

    
859
    // Verify that the block is shown on some pages, but not on others.
860
    $this->drupalGet('');
861
    $this->assertCasLoginBlock(TRUE);
862

    
863
    $this->drupalGet('user');
864
    $this->assertCasLoginBlock(FALSE);
865

    
866
    $this->drupalGet('user/1');
867
    $this->assertCasLoginBlock(TRUE);
868

    
869
    // Log in using the login block, and verify redirection works.
870
    $edit = array();
871
    $submit = t(variable_get('cas_login_invite', CAS_LOGIN_INVITE_DEFAULT));
872

    
873
    $this->drupalPost('', $edit, $submit);
874
    $this->assertLoggedIn($account);
875
    $this->assertUrl('node');
876

    
877
    // Block should not be shown to logged in users.
878
    $this->assertCasLoginBlock(FALSE);
879
  }
880
}