Project

General

Profile

Paste
Download (29 KB) Statistics
| Branch: | Revision:

root / drupal7 / sites / all / modules / cas / cas.test @ 38c269d5

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
    // Set CAS server url (will be altered).
35
    variable_set('cas_server', 'example.com');
36

    
37
    // Create admin user.
38
    $this->admin_user = $this->drupalCreateUser(array('administer users', 'administer cas'));
39

    
40
    // Download and extract in PHPCAS.
41
    $this->downloadExtractPhpCas('1.3.3');
42
  }
43

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

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

    
65
    // Local archive name.
66
    $local_archive = $simpletest_cache . '/' . $filename;
67
    $cas_library_dir = $simpletest_cache . '/' . $directory;
68

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

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

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

    
92
    // Set the CAS library directory.
93
    variable_set('cas_library_dir', $cas_library_dir);
94
  }
95

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

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

    
121
    // Restore password.
122
    $account->pass_raw = $pass_raw;
123
    return $account;
124
  }
125

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

    
140
    // Log in the user.
141
    $cas_name = $this->setCasUser($account, $attributes);
142
    $this->drupalGet('cas');
143

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

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

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

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

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

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

    
231
}
232

    
233
class CasUserAdminTestCase extends CasTestHelper {
234

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
360
/**
361
 * Test case to test user editing behavior.
362
 */
363
class CasUserTestCase extends CasTestHelper {
364

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

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

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

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

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

    
398
    // Create a new user.
399
    $user2 = $this->drupalCreateUser();
400
    $cas_name = $user2->name;
401
    $this->setCasUser($cas_name);
402

    
403
    // Test that CAS does not hijack an existing username.
404
    $this->drupalGet('cas');
405
    $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)));
406
  }
407

    
408
  function testUserEdit() {
409
    $cas_name = $this->randomName();
410
    $account = $this->casCreateUser($cas_name, array('change own username'));
411

    
412
    $this->casLogin($cas_name);
413

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

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

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

    
448
  function testNameToken() {
449
    $account = $this->casCreateUser();
450
    $this->casLogin($account);
451

    
452
    $this->assertToken('[cas:name]', $account->cas_name);
453
  }
454

    
455
  function testCaseInsensitiveLogin() {
456
    $account = $this->casCreateUser();
457
    $this->casLogin(strtoupper($account->cas_name));
458
    $this->assertLoggedIn($account);
459
  }
460

    
461
}
462

    
463
/**
464
 * Test case to test user logout behavior.
465
 */
466
class CasLogoutRedirectionTestCase extends CasTestHelper {
467

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

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

    
482
    $this->casLogin($account);
483
    $this->drupalGet('caslogout');
484
    $this->assertText('Logged out. No redirection provided.');
485
    $this->assertLoggedOut();
486

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

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

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

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

    
524
/**
525
 * Test case to test user login behavior.
526
 */
527
class CasLoginRedirectionTestCase extends CasTestHelper {
528

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

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

    
545
    // Create a CAS user.
546
    $account = $this->casCreateUser();
547
    $cas_name = $account->cas_name;
548
    $this->setCasUser($cas_name);
549

    
550
    // Test going to 'cas'
551
    $this->drupalGet('cas');
552
    $this->assertLoggedIn($account);
553
    $this->assertUrl('');
554
    $this->drupalLogout();
555

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

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

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

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

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

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

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

    
613
    // The second login should not be redirected.
614
    $this->casLogin($cas_name);
615
    $this->assertUrl('');
616
    $this->drupalLogout();
617

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

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

    
632
/**
633
 * Test CAS Single Sign-Out.
634
 */
635
class CasSingleSignOutTestCase extends CasTestHelper {
636

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

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

    
651
    cas_test_single_sign_out($cas_name);
652
    $this->assertLoggedOut();
653

    
654
    // @todo: Add additional tests for other methods of logging in (especially
655
    //   methods coming from cas_pages).
656
  }
657

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

    
664
    cas_test_single_sign_out($cas_name, TRUE);
665
    $this->assertLoggedOut();
666

    
667
    // @todo: Add additional tests for other methods of logging in (especially
668
    //   methods coming from cas_pages).
669
  }
670
}
671

    
672
/**
673
 * Test case for CAS gateway feature.
674
 */
675
class CasGatewayTestCase extends CasTestHelper {
676

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

    
685
  function setUp() {
686
    parent::setUp();
687
  }
688

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

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

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

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

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

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

    
739
/**
740
 * Test case for CAS force login feature.
741
 */
742
class CasRequiredLoginTestCase extends CasTestHelper {
743

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

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

    
761
    $this->drupalGet("node/$node2->nid");
762

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

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

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

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

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

    
794
    variable_set('cas_check_frequency', CAS_CHECK_ONCE);
795
    variable_set('cas_exclude', "node/$node->nid");
796

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

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

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

    
821
  function setUp() {
822
    parent::setUp();
823

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

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

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

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

    
866
    $this->drupalGet('user');
867
    $this->assertCasLoginBlock(FALSE);
868

    
869
    $this->drupalGet('user/1');
870
    $this->assertCasLoginBlock(TRUE);
871

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

    
876
    $this->drupalPost('', $edit, $submit);
877
    $this->assertLoggedIn($account);
878
    $this->assertUrl('node');
879

    
880
    // Block should not be shown to logged in users.
881
    $this->assertCasLoginBlock(FALSE);
882
  }
883
}