ClientTest.php #1

  • //
  • guest/
  • thomas_gray/
  • jambox/
  • main/
  • swarm/
  • tests/
  • phpunit/
  • P4Test/
  • Spec/
  • ClientTest.php
  • View
  • Commits
  • Open Download .zip Download (26 KB)
<?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'
        );
    }
}
# Change User Description Committed
#1 18730 Liz Lam clean up code and move things around