<?php /** * Test methods for the P4 Key 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\Key; use P4Test\TestCase; use P4\Key\Key; use P4\Counter\Counter; use P4\Connection\Connection; use P4\Connection\Exception\CommandException; class Test extends TestCase { /** * Verify keys don't mingle with counters */ public function testNoCounterOverlap() { $key = new Key; $key->setId('k1')->set('test'); $key->setId('k2')->set('test'); $counter = new Counter; $counter->setId('c1')->set('test'); $counter->setId('c2')->set('test'); $this->assertSame( array('k1', 'k2'), Key::fetchAll()->invoke('getId'), 'Expected to see all keys but nothing else' ); } /** * Test fetchAll method */ public function testFetchAll() { $entries = array( 'test1' => 'value1', 'test2' => 'value2', 'test3' => 'value3', 'test4' => 'value4', 'test5' => 'value5', 'test6' => 'value6', ); $this->assertSame( 0, count(Key::fetchAll()), 'Expected matching number of entries to start' ); // prime the data foreach ($entries as $id => $value) { $key = new Key; $key->setId($id)->set($value); } // run a fetch all and validate result $keys = Key::fetchAll(); foreach ($keys as $key) { $this->assertTrue( array_key_exists($key->getId(), $entries), 'Expected key '.$key->getId().' to exist in our entries array' ); $this->assertSame( $entries[$key->getId()], $key->get(), 'Expected matching key value for entry '.$key->getId() ); } // Verify fetchAll with made up option works $this->assertSame( count($entries), count(Key::fetchAll(array('fooBar' => true))), 'Expected fetch all with made up option to match' ); // Verify full FETCH_MAXIMUM works $this->assertSame( array_slice(array_keys($entries), 0, 3), Key::fetchAll(array(Key::FETCH_MAXIMUM => '3'))->invoke('getId'), 'Expected fetch all with Maximum to match' ); } /** * Ensure calling fetchAll() with FETCH_BY_NAME flag works. */ public function testFetchAllWithOptions() { // add keys to test $keys = array( 'testkey1', 'testkey2', 'testkey3', 'testa', 'testb', 'testk', 'key1', 'key2', 'testkey4' ); foreach ($keys as $id) { $key = new Key; $key->setId($id) ->set(1); } // define tests $tests = array( array( 'pattern' => 'testk', 'expected' => array( 'testk' ) ), array( 'pattern' => 'testk*', 'expected' => array( 'testkey1', 'testkey2', 'testkey3', 'testk', 'testkey4' ) ), array( 'pattern' => '*stk*', 'expected' => array( 'testkey1', 'testkey2', 'testkey3', 'testkey4', 'testk' ) ) ); // run tests foreach ($tests as $test) { $options = array( Key::FETCH_BY_NAME => $test['pattern'] ); $result = Key::fetchAll($options)->invoke('getId'); // sort resulting arrays as keys may come in different order // from the server sort($result); sort($test['expected']); $this->assertSame( $test['expected'], $result, 'for pattern ' . $test['pattern'] ); } } /** * Test fetchAll by ids */ public function testFetchAllByIds() { $entries = array( 'test1' => 'value1', 'test2' => 'value2', 'test3' => 'value3', 'test4' => 'value4', 'test5' => 'value5', 'test6' => 'value6', ); // prime the data foreach ($entries as $id => $value) { $key = new Key; $key->setId($id)->set($value); } $this->assertSame( array('test1', 'test3', 'test4', 'test6'), Key::fetchAll( array(Key::FETCH_BY_IDS => array('test1', 'test3', 'test4', 'test6', 'test-bad')) )->invoke('getId'), 'expected matching ids' ); } /** * Test calling set without an ID */ public function testSetNoId() { try { $key = new Key; $key->set('test'); $this->fail('unexpected success'); } catch (\PHPUnit\Framework\AssertionFailedError $e) { $this->fail($e->getMessage()); } catch (\P4\Exception $e) { $this->assertSame( "Cannot set value. No id has been set.", $e->getMessage(), 'unexpected exception message' ); } catch (\Exception $e) { $this->fail(': unexpected exception ('. get_class($e) .') '. $e->getMessage()); } } /** * Test the get value function */ public function testGetSet() { $key = new Key(); $key->setId('test')->set('testValue'); $key = Key::fetch('test'); $this->assertSame( 'test', $key->getId(), 'Expected matching Id' ); $this->assertSame( 'testValue', $key->get(), 'Expected matching value' ); Key::fetch('test')->set('testValue2'); $this->assertSame( 'testValue', $key->get(), 'Expected cached value after outside modification' ); $this->assertSame( 'testValue2', $key->get(true), 'Expected matching value after outside modification' ); $key = new Key; $this->assertSame( null, $key->get(), 'Expected no-id key value to match' ); $key->setId('newKey'); $this->assertSame( null, $key->get(), 'Expected non-existent key value to match' ); } /** * Test a good call to fetch */ public function testFetch() { $key = new Key(); $key->setId('test')->set('testValue'); $key = Key::fetch('test'); $this->assertSame( 'test', $key->getId(), 'Expected matching Id' ); $this->assertSame( 'testValue', $key->get(), 'Expected matching value' ); } /** * Test fetch of non-existent record */ public function testNonExistentFetch() { // ensure fetch fails for a non-existant key. try { Key::fetch('alskdfj2134'); $this->fail("Fetch should fail for a non-existant key."); } catch (\PHPUnit\Framework\AssertionFailedError $e) { $this->fail($e->getMessage()); } catch (\P4\Exception $e) { $this->assertSame( "Cannot fetch entry. Id does not exist.", $e->getMessage(), 'unexpected exception message' ); } catch (\Exception $e) { $this->fail(': unexpected exception ('. get_class($e) .') '. $e->getMessage()); } } /** * Test fetch of bad id record */ public function testBadIdFetch() { // ensure fetch fails for a bad Id. try { Key::fetch('te/st'); $this->fail("Fetch should fail for a il-formated key."); } catch (\PHPUnit\Framework\AssertionFailedError $e) { $this->fail($e->getMessage()); } catch (\InvalidArgumentException $e) { $this->assertSame( "Must supply a valid id to fetch.", $e->getMessage(), 'unexpected exception message' ); } catch (\Exception $e) { $this->fail(': unexpected exception ('. get_class($e) .') '. $e->getMessage()); } } /** * test bad values for setId */ public function testBadSetId() { $tests = array( array( 'title' => __LINE__." leading minus", 'value' => '-test' ), array( 'title' => __LINE__." forward slash", 'value' => 'te/st' ), array( 'title' => __LINE__." all numeric", 'value' => '1234' ), ); foreach ($tests as $test) { // ensure fetch fails for a non-existant key. try { $key = new Key; $key->setId($test['value']); $this->fail($test['title'].': unexpected success'); } catch (\PHPUnit\Framework\AssertionFailedError $e) { $this->fail($e->getMessage()); } catch (\InvalidArgumentException $e) { $this->assertSame( "Cannot set id. Id is invalid.", $e->getMessage(), $test['title'].': unexpected exception message' ); } catch (\Exception $e) { $this->fail($test['title'].': : unexpected exception ('. get_class($e) .') '. $e->getMessage()); } } } /** * Test exists */ public function testExists() { // ensure id-exists returns false for ill formatted key $this->assertFalse(Key::exists("-alsdjf"), "Leading - key id should not exist."); $this->assertFalse(Key::exists("als/djf"), "Forward slash key id should not exist."); // ensure id-exists returns false for non-existant key $this->assertFalse(Key::exists("alsdjf"), "Given key id should not exist."); // create key and ensure it exists. $group = new Key; $group->setId('test') ->set('tester'); $this->assertTrue(Key::exists("test"), "Given key id should exist."); } /** * Test the increment function */ public function testIncrement() { $key = new Key; // Test key that already exists, starting at 0 $key->setId('existing')->set(0); $this->assertSame( "1", $key->increment(), 'Expected matching value when starting at 0' ); $this->assertSame( "1", Key::fetch('existing')->get(), 'Expected matching value when starting at 0 on independent fetch' ); $this->assertSame( "2", $key->increment(), 'Expected matching value after second increment' ); $this->assertSame( "2", Key::fetch('existing')->get(), 'Expected matching value after second increment on independent fetch' ); // Test key that already exists starting at 1 $key->set(1); $this->assertSame( "2", $key->increment(), 'Expected matching value when starting at 2' ); // Test increment will create a key if it doesn't exist $key = new Key; $key->setId('newKey'); $this->assertSame( "1", $key->increment(), 'Expected matching value for new key' ); $this->assertSame( "1", Key::fetch('newKey')->get(), 'Expected matching value for new key on independent fetch' ); } /** * Test the increment function with bad starting value */ public function testBadIncrement() { // Test key that already exists, starting at 'bad' try { $key = new Key; $key->setId('existing')->set('bad'); $key->increment(); $this->fail("Increment should fail for a il-valued key."); } catch (\PHPUnit\Framework\AssertionFailedError $e) { $this->fail($e->getMessage()); } catch (\P4\Exception $e) { $this->assertSame( "Command failed: Can't increment counter 'existing' - value is not numeric.", $e->getMessage(), 'unexpected exception message' ); } catch (\Exception $e) { $this->fail(': unexpected exception ('. get_class($e) .') '. $e->getMessage()); } } /** * Test the delete function */ public function testDelete() { $key = new Key; $key->setId('test')->set('testValue'); $this->assertTrue(Key::exists('test'), 'expected test entry to exist'); $key->delete('test'); $this->assertFalse(Key::exists('test'), 'expected test entry was deleted'); $keys = Key::fetchAll(); $this->assertFalse( in_array('test', $keys->invoke('getId')), 'expected deleted entry would not be returned by fetchall' ); } /** * Test the delete function with non-existent id */ public function testMissingIdDelete() { try { $key = new Key; $key->setId('missing')->delete(); $this->fail("Delete should fail for a missing key."); } catch (\PHPUnit\Framework\AssertionFailedError $e) { $this->fail($e->getMessage()); } catch (\P4\Exception $e) { $this->assertSame( "Cannot delete entry. Id does not exist.", $e->getMessage(), 'unexpected exception message' ); } catch (\Exception $e) { $this->fail(': unexpected exception ('. get_class($e) .') '. $e->getMessage()); } } /** * Test the delete function with no id */ public function testNoIdDelete() { try { $key = new Key; $key->delete(); $this->fail("Delete should fail when no id is set."); } catch (\PHPUnit\Framework\AssertionFailedError $e) { $this->fail($e->getMessage()); } catch (\P4\Exception $e) { $this->assertSame( "Cannot delete. No id has been set.", $e->getMessage(), 'unexpected exception message' ); } catch (\Exception $e) { $this->fail(': unexpected exception ('. get_class($e) .') '. $e->getMessage()); } } }