- <?php
- /**
- * Test methods for the P4 Client class.
- *
- * @copyright 2012 Perforce Software. All rights reserved.
- * @license Please see LICENSE.txt in top-level folder of this distribution.
- * @version <release>/<patch>
- */
-
- namespace P4Test\Spec;
-
- use P4Test\TestCase;
- use P4\Spec\Client;
-
- class ClientTest extends TestCase
- {
- /**
- * Test initial conditions.
- */
- public function testInitialConditions()
- {
- $clients = Client::fetchAll();
- $this->assertSame(1, count($clients), 'Expected clients at start.');
- $client = $clients->first();
- $this->assertSame($this->getP4Params('client'), $client->getId(), 'Expected client name.');
- $this->assertSame(
- $this->getP4Params('user'),
- $client->getOwner(),
- 'Expected client owner.'
- );
- $this->assertSame(
- $this->getP4Params('clientRoot') .'/superuser',
- $client->getRoot(),
- 'Expected client root.'
- );
- $this->assertSame('', $client->getHost(), 'Expected client host.');
- $this->assertSame('', $client->getDescription(), 'Expected client description.');
- $this->assertSame('local', $client->getLineEnd(), 'Expected client line ending.');
- $this->assertSame(
- array(
- 'noallwrite', 'noclobber', 'nocompress', 'unlocked',
- 'nomodtime', 'normdir',
- ),
- $client->getOptions(),
- 'Expected options'
- );
- $this->assertSame(
- array(
- array(
- 'depot' => '//depot/...',
- 'client' => '//'. $this->getP4Params('client') .'/...',
- ),
- ),
- $client->getView(),
- 'Expected client view.'
- );
-
- $this->assertTrue(
- Client::exists($this->getP4Params('client')),
- 'Expect configured client to exist.'
- );
- $this->assertFalse(
- Client::exists('foobar'),
- 'Expect bogus client to not exist.'
- );
- $this->assertFalse(
- Client::exists(123),
- 'Expect invalid client to not exist.'
- );
- }
-
- /**
- * Test a fresh in-memory Client object.
- */
- public function testFreshObject()
- {
- $client = new Client;
- $this->assertSame(
- null,
- $client->getUpdateDateTime(),
- 'Expected update datetime'
- );
- $this->assertSame(
- null,
- $client->getAccessDateTime(),
- 'Expected access datetime'
- );
- $this->assertSame(
- null,
- $client->getRoot(),
- 'Expected null client root'
- );
- }
-
- /**
- * Test accessors/mutators.
- */
- public function testAccessorsMutators()
- {
- $client = new Client;
- $tests = array(
- 'Client' => 'zclient',
- 'Description' => 'zdesc',
- 'Host' => 'zhost',
- 'LineEnd' => 'zle',
- 'Owner' => 'bob',
- 'Root' => 'zroot',
- );
-
- foreach ($tests as $key => $value) {
- $client->set($key, $value);
- $this->assertSame($value, $client->get($key), "Expected value for $key");
- }
-
- $client->set('View', array('a view'));
- $this->assertSame(
- array(array('depot' => 'a', 'client' => 'view')),
- $client->get('View'),
- 'Expected view.'
- );
- }
-
- /**
- * Test setView.
- */
- public function testSetView()
- {
- $badTypeError = "Each view entry must be a 'depot' and 'client' array or a string.";
- $badFormatError = "Each view entry must contain two paths, no more, no less.";
- $tests = array(
- array(
- 'label' => __LINE__ .': null',
- 'view' => null,
- 'expect' => false,
- 'error' => 'View must be passed as array.',
- ),
- array(
- 'label' => __LINE__ .': empty array',
- 'view' => array(),
- 'expect' => array(),
- 'error' => false,
- ),
- array(
- 'label' => __LINE__ .': array containing int',
- 'view' => array(12),
- 'expect' => false,
- 'error' => $badTypeError,
- ),
- array(
- 'label' => __LINE__ .': array with empty string',
- 'view' => array(''),
- 'expect' => false,
- 'error' => $badFormatError,
- ),
- array(
- 'label' => __LINE__ .': array with bogus string',
- 'view' => array('qstring'),
- 'expect' => false,
- 'error' => $badFormatError,
- ),
- array(
- 'label' => __LINE__ .': array with string, integer',
- 'view' => array('a string', 12),
- 'expect' => false,
- 'error' => $badTypeError,
- ),
- array(
- 'label' => __LINE__ .': array with string, bogus string',
- 'view' => array('a string', 'bogus'),
- 'expect' => false,
- 'error' => $badFormatError,
- ),
- array(
- 'label' => __LINE__ .': array with string',
- 'view' => array('a string'),
- 'expect' => array(
- array('depot' => 'a', 'client' => 'string'),
- ),
- 'error' => false,
- ),
- array(
- 'label' => __LINE__ .': array with strings',
- 'view' => array('a string', '"another" string', "third 'entry'"),
- 'expect' => array(
- array('depot' => 'a', 'client' => 'string'),
- array('depot' => 'another', 'client' => 'string'),
- array('depot' => 'third', 'client' => "'entry'"),
- ),
- 'error' => false,
- ),
- array(
- 'label' => __LINE__ .': array with empty array',
- 'view' => array(array()),
- 'expect' => false,
- 'error' => $badTypeError,
- ),
- array(
- 'label' => __LINE__ .': array with good array + bad array',
- 'view' => array(
- array('depot' => 'depot', 'client' => 'client'),
- array(),
- ),
- 'expect' => false,
- 'error' => $badTypeError,
- ),
- array(
- 'label' => __LINE__ .': array with array, no client',
- 'view' => array(array('depot' => 'a')),
- 'expect' => false,
- 'error' => $badTypeError,
- ),
- array(
- 'label' => __LINE__ .': array with array, no depot',
- 'view' => array(array('client' => 'a')),
- 'expect' => false,
- 'error' => $badTypeError,
- ),
- array(
- 'label' => __LINE__ .': array with array + extra',
- 'view' => array(
- array('depot' => 'depot', 'client' => 'client', 'a' => 'b')
- ),
- 'expect' => array(
- array('depot' => 'depot', 'client' => 'client'),
- ),
- 'error' => false,
- ),
- array(
- 'label' => __LINE__ .': array with good array + string',
- 'view' => array(
- array('depot' => 'depot', 'client' => 'client'),
- 'another client',
- ),
- 'expect' => array(
- array('depot' => 'depot', 'client' => 'client'),
- array('depot' => 'another', 'client' => 'client'),
- ),
- 'error' => false,
- ),
- array(
- 'label' => __LINE__ .': array with good arrays',
- 'view' => array(
- array('depot' => 'depot', 'client' => 'client'),
- array('depot' => 'builds', 'client' => 'buildClient'),
- array('depot' => 'cms', 'client' => 'cmsClient'),
- ),
- 'expect' => array(
- array('depot' => 'depot', 'client' => 'client'),
- array('depot' => 'builds', 'client' => 'buildClient'),
- array('depot' => 'cms', 'client' => 'cmsClient'),
- ),
- 'error' => false,
- ),
- );
-
- foreach ($tests as $test) {
- $label = $test['label'];
- $client = new Client;
- try {
- $client->setView($test['view']);
- if ($test['error']) {
- $this->fail("$label - unexpected success");
- }
- } catch (\InvalidArgumentException $e) {
- if ($test['error']) {
- $this->assertSame(
- $test['error'],
- $e->getMessage(),
- 'Expected error message.'
- );
- } else {
- $this->fail("$label - unexpected argument exception.");
- }
- } catch (\PHPUnit\Framework\AssertionFailedError $e) {
- $this->fail($e->getMessage());
- } catch (\Exception $e) {
- $this->fail(
- "$label - Unexpected exception (". get_class($e)
- .") - ". $e->getMessage()
- );
- }
-
- if (!$test['error']) {
- $this->assertSame(
- $test['expect'],
- $client->getView(),
- "$label - expected view after set"
- );
- }
- }
- }
-
- /**
- * Test addView.
- */
- public function testAddView()
- {
- $error = "Each view entry must be a 'depot' and 'client' array or a string.";
- $tests = array(
- array(
- 'label' => __LINE__ .': null, null',
- 'depot' => null,
- 'client' => null,
- 'error' => $error,
- 'expect' => array(),
- ),
- array(
- 'label' => __LINE__ .': numeric, numeric',
- 'depot' => 1,
- 'client' => 2,
- 'error' => $error,
- 'expect' => array(),
- ),
- array(
- 'label' => __LINE__ .': null, string',
- 'depot' => null,
- 'client' => 'string',
- 'error' => $error,
- 'expect' => array(),
- ),
- array(
- 'label' => __LINE__ .': string, null',
- 'depot' => 'string',
- 'client' => null,
- 'error' => $error,
- 'expect' => array(),
- ),
- array(
- 'label' => __LINE__ .': numeric, string',
- 'depot' => 1,
- 'client' => 'string',
- 'error' => $error,
- 'expect' => array(),
- ),
- array(
- 'label' => __LINE__ .': string, numeric',
- 'depot' => 'string',
- 'client' => 1,
- 'error' => $error,
- 'expect' => array(),
- ),
- array(
- 'label' => __LINE__ .': empty, empty',
- 'depot' => 'depot',
- 'client' => 'client',
- 'error' => false,
- 'expect' => array(
- array(
- 'depot' => 'depot',
- 'client' => 'client',
- ),
- ),
- ),
- );
-
- foreach ($tests as $test) {
- $label = $test['label'];
- $client = new Client;
- try {
- $client->addView($test['depot'], $test['client']);
- if ($test['error']) {
- $this->fail("$label - unexpected success");
- }
- } catch (\InvalidArgumentException $e) {
- if ($test['error']) {
- $this->assertSame(
- $test['error'],
- $e->getMessage(),
- 'Expected error message.'
- );
- } else {
- $this->fail("$label - unexpected argument exception.");
- }
- } catch (\PHPUnit\Framework\AssertionFailedError $e) {
- $this->fail($e->getMessage());
- } catch (\Exception $e) {
- $this->fail(
- "$label - Unexpected exception (". get_class($e)
- .") - ". $e->getMessage()
- );
- }
-
- if (!$test['error']) {
- $this->assertSame(
- $test['expect'],
- $client->getView(),
- "$label - expected view after set"
- );
- }
- }
-
- }
-
- /**
- * test the touchup view function
- */
- public function testTouchUpView()
- {
- $expected = array(
- array(
- 'depot' => '//depot/foo/...',
- 'client' => '//newclient/foo/...',
- ),
- array(
- 'depot' => '//depot/foo/...',
- 'client' => '//newclient/foo/...',
- ),
- array(
- 'depot' => '//depot/foo/...',
- 'client' => '//newclient/foo/...',
- )
- );
-
- $client = new Client;
- $client->setView(
- array(
- '//depot/foo/... //oldclient-1/foo/...',
- '//depot/foo/... //oldClient2/foo/...',
- '//depot/foo/... //newclient/foo/...'
- )
- );
- $client->setId('newclient')->touchUpView();
-
- $this->assertSame($expected, $client->getView());
- }
-
- /**
- * Test setOptionsSubmitOptions.
- */
- public function testSetOptionsSubmitOptions()
- {
- $tests = array(
- array(
- 'label' => __LINE__ .': null',
- 'options' => null,
- 'expect' => false,
- 'error' => true,
- ),
- array(
- 'label' => __LINE__ .': empty string',
- 'options' => '',
- 'expect' => array(),
- 'error' => false,
- ),
- array(
- 'label' => __LINE__ .': string',
- 'options' => 'bob',
- 'expect' => array('bob'),
- 'error' => false,
- ),
- array(
- 'label' => __LINE__ .': integer',
- 'options' => 3,
- 'expect' => false,
- 'error' => true,
- ),
- array(
- 'label' => __LINE__ .': array',
- 'options' => array(),
- 'expect' => array(),
- 'error' => false,
- ),
- );
-
- $types = array ('Options', 'SubmitOptions');
- foreach ($types as $type) {
- $typeLabel = ($type == 'SubmitOptions') ? 'Submit Options' : $type;
- $setMethod = "set$type";
- $getMethod = "get$type";
- foreach ($tests as $test) {
- $label = $test['label'];
- $client = new Client;
- try {
- $client->$setMethod($test['options']);
- if ($test['error']) {
- $this->fail("$label - unexpected success");
- }
- } catch (\InvalidArgumentException $e) {
- if ($test['error']) {
- $this->assertSame(
- "$typeLabel must be an array or string",
- $e->getMessage(),
- 'Expected error message.'
- );
- } else {
- $this->fail("$label - unexpected argument exception.");
- }
- } catch (\PHPUnit\Framework\AssertionFailedError $e) {
- $this->fail($e->getMessage());
- } catch (\Exception $e) {
- $this->fail(
- "$label - Unexpected exception (". get_class($e)
- .") - ". $e->getMessage()
- );
- }
-
- if (!$test['error']) {
- $this->assertSame(
- $test['expect'],
- $client->$getMethod(),
- "$label - expected $type after set"
- );
- }
- }
- }
- }
-
- /**
- * Test setId, setDescription, setHost, setLineEnd, setOwner, setRoot.
- */
- public function testSetIdDescriptionHostLineEndOwnerRoot()
- {
- $tests = array(
- array(
- 'label' => __LINE__ .': null',
- 'value' => null,
- 'error' => false,
- ),
- array(
- 'label' => __LINE__ .': empty string',
- 'value' => '',
- 'error' => false,
- ),
- array(
- 'label' => __LINE__ .': string',
- 'value' => 'bob',
- 'error' => false,
- ),
- array(
- 'label' => __LINE__ .': integer',
- 'value' => 3,
- 'error' => true,
- ),
- );
-
- $types = array('Id', 'Description', 'Host', 'LineEnd', 'Owner', 'Root');
- foreach ($types as $type) {
- $typeLabel = ($type == 'LineEnd') ? 'Line End' : $type;
- $setMethod = "set$type";
- $getMethod = "get$type";
-
- foreach ($tests as $test) {
- $label = $test['label'] ." ($type)";
- $client = new Client;
-
- // setup the expected error message
- $expectedError = "$typeLabel must be a string or null.";
- // Client id validation fails on empty string now, which
- // is the only exception (so far), so we special case it here.
- if ($type == 'Id') {
- $expectedError = 'Cannot set id. Id is invalid.';
-
- if (preg_match('/empty string/', $label)) {
- $test['error'] = true;
- }
- }
-
- try {
- $client->$setMethod($test['value']);
- if ($test['error']) {
- $this->fail("$label - unexpected success");
- }
- } catch (\InvalidArgumentException $e) {
- if ($test['error']) {
- $this->assertSame(
- $expectedError,
- $e->getMessage(),
- "$label - Expected error message."
- );
- } else {
- $this->fail("$label - unexpected argument exception.");
- }
- } catch (\PHPUnit\Framework\AssertionFailedError $e) {
- $this->fail($e->getMessage());
- } catch (\Exception $e) {
- $this->fail(
- "$label - Unexpected exception (". get_class($e)
- .") - ". $e->getMessage()
- );
- }
-
- if (!$test['error']) {
- $this->assertSame(
- $test['value'],
- $client->$getMethod(),
- "$label - expected $type after set"
- );
- }
- }
- }
- }
-
- /**
- * Test fetchAll filtered by Owner
- */
- public function testFetchAllByOwner()
- {
- // 'test-client' will exist out of the gate; add a couple more to make it a real test.
- $this->createClients();
-
- $byOwner = Client::fetchAll(array(Client::FETCH_BY_OWNER => 'user1'));
-
- $this->assertSame(
- 2,
- count($byOwner),
- 'Expected matching number of results'
- );
-
- $this->assertSame(
- 'test2-client',
- $byOwner->first()->getId(),
- 'Expected first result client to match'
- );
-
- $this->assertSame(
- 'user1',
- $byOwner->first()->getOwner(),
- 'Expected first result user to match'
- );
-
- $this->assertSame(
- 'test3-client',
- $byOwner->nth(1)->getId(),
- 'Expected second result client to match'
- );
-
- $this->assertSame(
- 'user1',
- $byOwner->nth(1)->getOwner(),
- 'Expected second result user to match'
- );
-
- // Verify invalid names causes error
- $tests = array(
- __LINE__ .' int' => 10,
- __LINE__ .' bool' => false
- );
-
- foreach ($tests as $label => $value) {
- try {
- Client::fetchAll(array(Client::FETCH_BY_OWNER => $value));
-
- $this->fail($label.': Expected filter to fail');
- } catch (\PHPUnit\Framework\AssertionFailedError $e) {
- throw $e;
- } catch (\InvalidArgumentException $e) {
- $this->assertSame(
- 'Filter by Owner expects a non-empty string as input',
- $e->getMessage(),
- $label.':Unexpected Exception message'
- );
- } catch (\Exception $e) {
- $this->fail(
- $label.':Unexpected Exception ('. get_class($e) .'): '. $e->getMessage()
- );
- }
- }
-
- }
-
- /**
- * Test fetchAll filtered by Name
- */
- public function testFetchAllByName()
- {
- // 'test-client' will exist out of the gate; add a couple more to make it a real test.
- $this->createClients();
-
- $byOwner = Client::fetchAll(array(Client::FETCH_BY_NAME => 'test3-*'));
-
- $this->assertSame(
- 2,
- count($byOwner),
- 'Expected matching number of results'
- );
-
- $this->assertSame(
- 'test3-client',
- $byOwner->first()->getId(),
- 'Expected first result client to match'
- );
-
- $this->assertSame(
- 'test3-clientb',
- $byOwner->nth(1)->getId(),
- 'Expected second result client to match'
- );
-
- // Verify invalid names causes error
- $tests = array(
- __LINE__ .' empty string' => "",
- __LINE__ .' bool' => false
- );
-
- foreach ($tests as $label => $value) {
- try {
- Client::fetchAll(array(Client::FETCH_BY_NAME => $value));
-
- $this->fail($label.': Expected filter to fail');
- } catch (\PHPUnit\Framework\AssertionFailedError $e) {
- throw $e;
- } catch (\InvalidArgumentException $e) {
- $this->assertSame(
- 'Filter by Name expects a non-empty string as input',
- $e->getMessage(),
- $label.':Unexpected Exception message'
- );
- } catch (\Exception $e) {
- $this->fail(
- $label.':Unexpected Exception ('. get_class($e) .'): '. $e->getMessage()
- );
- }
- }
- }
-
- /**
- * Test fetchAll filtered by Owner and filtered by Name
- */
- public function testFetchAllByOwnerAndName()
- {
- // 'test-client' will exist out of the gate; add a couple more to make it a real test.
- $this->createClients();
-
- $byOwner = Client::fetchAll(
- array(
- Client::FETCH_BY_NAME => 'test3-*',
- Client::FETCH_BY_OWNER => 'user1'
- )
- );
-
- $this->assertSame(
- 1,
- count($byOwner),
- 'Expected matching number of results'
- );
-
- $this->assertSame(
- 'test3-client',
- $byOwner->first()->getId(),
- 'Expected first result client to match'
- );
- }
-
- /**
- * Make some clients for testing fetch all.
- */
- protected function createClients()
- {
- $client = new Client;
- $client->setId('test2-client')
- ->setOwner('user1')
- ->setRoot(DATA_PATH . '/clients/test2-client')
- ->save();
- $client->setId('test3-client')
- ->setOwner('user1')
- ->setRoot(DATA_PATH . '/clients/test3-client')
- ->save();
- $client->setId('test3-clientb')
- ->setOwner('user2')
- ->setRoot(DATA_PATH . '/clients/test3-clientb')
- ->save();
- }
-
- /**
- * Test creation of temp objects.
- */
- public function testMakeTemp()
- {
- // ensure we only have one client at start
- $this->assertSame(
- array('test-client'),
- Client::fetchAll()->invoke('getId')
- );
-
- $client = Client::makeTemp(array('Root' => DATA_PATH));
-
- $callbackCount = 0;
- $client2 = Client::makeTemp(
- array('Root' => DATA_PATH),
- function ($client, $defaultCallback) use (&$callbackCount) {
- $callbackCount++;
- $defaultCallback($client);
- }
- );
-
- $this->assertSame(
- 3,
- count(Client::fetchAll()),
- 'expected matching number of clients after our adds'
- );
-
- $client->getConnection()->disconnect();
-
- $this->assertSame(
- array('test-client'),
- Client::fetchAll()->invoke('getId'),
- 'expected matching number of clients after disconnect'
- );
-
- $this->assertSame(
- 1,
- $callbackCount,
- 'expected our callback count to have incremented'
- );
- }
- }