Archive: Namaste PHP AMQP framework v1.0 (2017-2020)

952 days continuous production uptime, 40k+ tp/s single node.
Original corpo Bitbucket history not included — clean archive commit.
This commit is contained in:
2026-04-05 09:49:30 -07:00
commit 373ebc8c93
1284 changed files with 409372 additions and 0 deletions

21
tests/unit/README.md Normal file
View File

@@ -0,0 +1,21 @@
Unit Tests
==========
Everyone's favorite subject, amirite?
So, if you're wanting to get started with the developer unit tests instead of writing your own,
feel free to use/borrow/steal these.
In the ./tests/unit/data directory you'll find dumps for both mySQL and mongoDB tables.
Note that unit tests use the gaTest_tst collection/table in both schemas. For mongoDB, the collection
is created in the {env}_givva_namaste database. (Not the admin db!)
Unit test require a somewhat significant amount of data. Still, even these data files may not
provide you with the stretch room you need. If you get a unit test that fails, try running the test
again. Often times, there just wasn't enough data to meet the query criteria for the test.
Note that, for every dev merge into master, all unit tests are run until all are green prior to the merge.
--Micheal Shallop
On Jul 25, 2018

View File

@@ -0,0 +1,361 @@
<?php
$_REDIRECT = false;
require(dirname(__DIR__) . '/../config/sneakerstrap.inc'); // and load the namaste environment
use PHPUnit\Framework\TestCase;
class apiClientAuthTest extends TestCase
{
protected ?gacBrokerClient $readBrokerClient = null;
protected static ?array $meta = null;
/**
* setUpBeforeClass() -- public static unit test method
*
* this method is called first, and once, on execution. This method calls the setUpBeforeClass() method and then
* established the meta data payloads we'll use for client and admin event requests.
*
* NOTE:
* -----
* You have to ensure that the GUID value assigned to CLIENT_AUTH_TOKEN exists and that the same value has been
* set in the gatTestMongo template constructor.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 06-02-20 mks ECI-108: original coding
*
*/
public static function setUpBeforeClass()
{
parent::setUpBeforeClass();
// meta data (for namaste)
static::$meta = [
META_DO_CACHE => false, // disable cache-mapping for the request
META_LIMIT => 1, // return one record only in the test-fetch query
META_CLIENT => CLIENT_API_USER, // simulate an API call to Namaste
CLIENT_AUTH_TOKEN => '79344859-5403-1556-7663-4E34D6B4CBE4',
META_CLIENT_IP => STRING_SESSION_HOME,
META_SYSTEM_NOTES => STRING_ORIGIN_UT,
META_TEMPLATE => TEMPLATE_CLASS_TEST_MONGO
];
}
/**
* setUp() -- unit test reserved method
*
* the setUp method is executed prior to each test, executing the following tasks:
*
* 1. validate that the meta data persisted across tests
* 2. validate that we successfully created a read-broker client
*
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 06-02-20 mks ECI-108: original coding
*
*/
protected function setUp()
{
parent::setUp();
$file = basename(__FILE__);
// validate the meta data for the pending query
$this->assertTrue(!empty(static::$meta), $file . AT . __LINE__ . COLON . ERROR_DATA_META_404);
$this->assertTrue(is_array(static::$meta), $file . AT . __LINE__ . COLON . ERROR_META_INVALID_FORMAT_ARRAY);
$this->assertTrue(array_key_exists(META_TEMPLATE, static::$meta), $file . AT . __LINE__ . COLON . ERROR_DATA_META_KEY_404 . META_TEMPLATE);
$this->assertTrue(array_key_exists(CLIENT_AUTH_TOKEN, static::$meta), $file . AT . __LINE__ . COLON . ERROR_DATA_META_KEY_404 . CLIENT_AUTH_TOKEN);
// create the read broker client
$this->readBrokerClient = new gacBrokerClient(BROKER_QUEUE_R, $file . AT . __LINE__);
$this->assertTrue($this->readBrokerClient->status, $file . AT . __LINE__ . COLON . ERROR_BROKER_QUEUE_DECLARE . BROKER_QUEUE_R);
}
/**
* tearDown() -- unit test method
*
* This is the (reserved) tearDown method which is executed at the end of every test. The method deletes the
* current broker client to clean-up the heap.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 06-02-20 mks ECI-108: original coding
*
*/
protected function tearDown()
{
if (is_object($this->readBrokerClient)) $this->readBrokerClient->__destruct();
unset($this->readBrokerClient);
}
/**
* testFetch() -- unit test method
*
* This test is a positive test - we expect this test to successfully fetch a random record with the implication
* being that the request was validated in Namaste by comparing the meta-payload's auth key to the authKey token
* stored in the template.
*
* As such, we don't really care about the return payload other than we returned a record, and only record. We're
* testing the ability to successfully fetch a record while mimic'ing an API request. Tests for the accuracy of
* the data are handled in other tests.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 06-02-20 mks ECI-108: original coding
*
*/
/**
*/
public function testFetch()
{
$meth = basename(__METHOD__);
// assertions that the static data is set and accessible
$this->assertTrue(is_array(static::$meta), sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_LOST_VARIABLE . STRING_META);
$this->assertNotEmpty(static::$meta, sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_LOST_VARIABLE . STRING_META);
$query = null; // fetch any active record
// set-up the broker fetch payload
$payload = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [
STRING_QUERY_DATA => $query
],
BROKER_META_DATA => static::$meta
];
// submit generic fetch request to namaste read broker
$response = json_decode(gzuncompress($this->readBrokerClient->call(gzcompress(json_encode($payload)))),true);
// test the response payload
$this->assertTrue($response[PAYLOAD_STATUS], sprintf(INFO_LOC, $meth, __LINE__) . sprintf(ERROR_UT_BROKER_EVENT_FAIL, BROKER_REQUEST_FETCH, $response[PAYLOAD_STATE]));
$recCount = count($response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS]);
$this->assertEquals(1, $recCount, sprintf(INFO_LOC, $meth, __LINE__) . sprintf(ERROR_UT_INTEGER_MISMATCH, 1, $recCount));
}
/**
* testNegativeNoAuthToken() -- unit test method
*
* This unit test is a negative test; we expect the request to Namaste to fail with the reason being is that we've
* pulled/deleted the client-auth-token from the meta payload. This should cause the request to be rejected by
* namaste (in the functions.inc validation, rather than in the factory-class validation code) returning a meta
* data error for the error state and an white-box error message. (We'll test for both.)
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 06-02-20 mks ECI-108: original coding
*
*/
public function testNegativeNoAuthToken()
{
$meth = basename(__METHOD__);
// assertions that the static data is set and accessible
$this->assertTrue(is_array(static::$meta), sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_LOST_VARIABLE . STRING_META);
$this->assertNotEmpty(static::$meta, sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_LOST_VARIABLE . STRING_META);
$metaCopy = static::$meta;
unset($metaCopy[CLIENT_AUTH_TOKEN]);
$this->assertArrayNotHasKey(CLIENT_AUTH_TOKEN, $metaCopy, sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_GENERIC_FAIL . 'did not remove client auth key from meta copy');
$query = null;
$payload = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [
STRING_QUERY_DATA => $query
],
BROKER_META_DATA => $metaCopy
];
// submit generic fetch request to namaste read broker
$response = json_decode(gzuncompress($this->readBrokerClient->call(gzcompress(json_encode($payload)))),true);
// we expect a failed (false) return because the meta payload is missing the client auth key token
$this->assertFalse($response[PAYLOAD_STATUS], sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_EXPECTING_FALSE . PAYLOAD_STATUS);
$this->assertEquals(STATE_META_ERROR, $response[PAYLOAD_STATE], sprintf($meth, __LINE__) . sprintf(ERROR_UT_STRING_MISMATCH, STATE_META_ERROR, $response[PAYLOAD_STATE]));
}
/**
* testNegativeMalformedToken() -- unit test method
*
* This is another negative unit test; we expect this test to fail because we're passing a malformed token value
* as the client-auth-token value. As in the previous test, this request should be rejected by Namaste at the
* broker-level instead of allowing the request to proceed deeper into the class-instantiation level.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 06-02-20 mks ECI-108: original coding
*
*/
public function testNegativeMalformedToken()
{
$meth = basename(__METHOD__);
// assertions that the static data is set and accessible
$this->assertTrue(is_array(static::$meta), sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_LOST_VARIABLE . STRING_META);
$this->assertNotEmpty(static::$meta, sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_LOST_VARIABLE . STRING_META);
$metaCopy = static::$meta;
// token is malformed
$metaCopy[CLIENT_AUTH_TOKEN] = '18D5C150-4639-32C8-07CD';
$query = null;
$payload = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [
STRING_QUERY_DATA => $query
],
BROKER_META_DATA => $metaCopy
];
// submit generic fetch request to namaste read broker
$response = json_decode(gzuncompress($this->readBrokerClient->call(gzcompress(json_encode($payload)))),true);
// we expect a failed (false) return because the meta payload is missing the client auth key token
$this->assertFalse($response[PAYLOAD_STATUS], sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_EXPECTING_FALSE . PAYLOAD_STATUS);
$this->assertEquals(STATE_DATA_ERROR, $response[PAYLOAD_STATE], sprintf(INFO_LOC, $meth, __LINE__) . sprintf(ERROR_UT_STRING_MISMATCH, STATE_META_ERROR, $response[PAYLOAD_STATE]));
}
/**
* testNegativeWrongToken() -- unit test method
*
* This test makes a request against a template requiring authentication but provides the wrong (incorrect)
* authentication token in the payload. As such, we should return, in this limited case an authentication error
* as opposed to a not-found error.
*
* Think of two scenarios - one is that we submit a superfluous token that doesn't exist (this test) or we submit
* a token that's exists, but isn't the correct value as defined in the data template (next test).
*
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 06-04-20 mks ECI-108: Original coding
*
*/
public function testNegativeMeaninglessToken()
{
$meth = basename(__METHOD__);
// assertions that the static data is set and accessible
$this->assertTrue(is_array(static::$meta), sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_LOST_VARIABLE . STRING_META);
$this->assertNotEmpty(static::$meta, sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_LOST_VARIABLE . STRING_META);
$metaCopy = static::$meta;
// token is incorrect, but valid - but doesn't like to any record in the db
$metaCopy[CLIENT_AUTH_TOKEN] = '18D5C150-4639-32C8-07CD-C7CD5970675F';
$query = null;
$payload = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [
STRING_QUERY_DATA => $query
],
BROKER_META_DATA => $metaCopy
];
// submit generic fetch request to namaste read broker
$response = json_decode(gzuncompress($this->readBrokerClient->call(gzcompress(json_encode($payload)))),true);
// we expect a failed (false) return because the meta payload is missing the client auth key token
$this->assertFalse($response[PAYLOAD_STATUS], sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_EXPECTING_FALSE . PAYLOAD_STATUS);
$this->assertEquals(STATE_DATA_ERROR, $response[PAYLOAD_STATE], sprintf(INFO_LOC, $meth, __LINE__) . sprintf(ERROR_UT_STRING_MISMATCH, STATE_AUTH_ERROR, $response[PAYLOAD_STATE]));
}
/**
* testNegativeWrongClient() -- unit test method
*
* This unit test is designed to fail - we're going to submit a request for a record and the client auth token
* is linked to an active, valid, smax-token record. However, it's not the record that's defined in the template.
* This test covers the case were Partner A attempts to instantiate a data template belonging to Partner B.
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 06-04-20 mks ECI-108: Original coding
*
*/
public function testNegativeWrongClient()
{
$meth = basename(__METHOD__);
// assertions that the static data is set and accessible
$this->assertTrue(is_array(static::$meta), sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_LOST_VARIABLE . STRING_META);
$this->assertNotEmpty(static::$meta, sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_LOST_VARIABLE . STRING_META);
$metaCopy = static::$meta;
// token is to another active record other than the one defined in the template
$metaCopy[CLIENT_AUTH_TOKEN] = '136EA67A-B1E2-0A4B-2BD8-EE34D39DFDE1';
$query = null;
$payload = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [
STRING_QUERY_DATA => $query
],
BROKER_META_DATA => $metaCopy
];
// submit generic fetch request to namaste read broker
$response = json_decode(gzuncompress($this->readBrokerClient->call(gzcompress(json_encode($payload)))),true);
// we expect a failed (false) return because the meta payload is missing the client auth key token
$this->assertFalse($response[PAYLOAD_STATUS], sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_EXPECTING_FALSE . PAYLOAD_STATUS);
$this->assertEquals(STATE_DATA_ERROR, $response[PAYLOAD_STATE], sprintf(INFO_LOC, $meth, __LINE__) . sprintf(ERROR_UT_STRING_MISMATCH, STATE_AUTH_ERROR, $response[PAYLOAD_STATE]));
}
/**
* testNegativeRequestFromDeletedClient() -- unit test method
*
* This test is a negative test - we expect the request to fail. In this test, we're submitting a fetch request
* using a client auth token from a deleted record; the smax token record is no longer in an active state.
*
* The return message doesn't give away the status of the record - we don't want the white-box user to know anything
* other than they encountered an authentication error.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 06-04-20 mks ECI-108: Original coding
*
*/
public function testNegativeRequestFromDeletedClient()
{
$meth = basename(__METHOD__);
// assertions that the static data is set and accessible
$this->assertTrue(is_array(static::$meta), sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_LOST_VARIABLE . STRING_META);
$this->assertNotEmpty(static::$meta, sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_LOST_VARIABLE . STRING_META);
$metaCopy = static::$meta;
// token is to a deleted record other than the one defined in the template
$metaCopy[CLIENT_AUTH_TOKEN] = 'B79652AA-6EA5-27CB-74DD-814E7BFAAD66';
$query = null;
$payload = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [
STRING_QUERY_DATA => $query
],
BROKER_META_DATA => $metaCopy
];
// submit generic fetch request to namaste read broker
$response = json_decode(gzuncompress($this->readBrokerClient->call(gzcompress(json_encode($payload)))),true);
// we expect a failed (false) return because the meta payload is missing the client auth key token
$this->assertFalse($response[PAYLOAD_STATUS], sprintf(INFO_LOC, $meth, __LINE__) . ERROR_UT_EXPECTING_FALSE . PAYLOAD_STATUS);
$this->assertEquals(STATE_DATA_ERROR, $response[PAYLOAD_STATE], sprintf(INFO_LOC, $meth, __LINE__) . sprintf(ERROR_UT_STRING_MISMATCH, STATE_AUTH_ERROR, $response[PAYLOAD_STATE]));
}
}

View File

@@ -0,0 +1,230 @@
<?php
/**
* Created by PhpStorm.
* User: mshallop
* Date: 6/16/17
* Time: 10:19 AM
*/
$_REDIRECT = false;
require(dirname(__DIR__) . '/../config/sneakerstrap.inc'); // and load the namaste environment
use PHPUnit\Framework\TestCase;
class brokerStartupTest extends TestCase
{
protected ?gacBrokerClient $brokerClient;
protected ?gacWorkQueueClient $brokerAdminInClient;
protected static ?gacErrorLogger $logger;
protected static array $brokerList;
/**
* setUpBeforeClass() -- public static unit test method
*
* this method is called first, and once, on execution. It sets up a list of brokers we're going to test.
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 06-16-17 mks original coding
*
*/
public static function setUpBeforeClass()
{
parent::setUpBeforeClass();
// defines the list of brokers we're going to test
static::$brokerList = [BROKER_QUEUE_R, BROKER_QUEUE_W, BROKER_QUEUE_AO, BROKER_QUEUE_AI];
}
/**
* testTimers -- unit test
*
* this method tests the base functionality of the f/w's timer function. We'll make a call to the timer to get
* a non-zero starting time, and test, and then make a second call to the function (which calculates the time
* elapsed) and test that this, too, is non-zero.
*
* Criteria for success: both tested values are non-zero
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 06-16-17 mks original coding
*
*/
public function testTimers()
{
/** @noinspection PhpUnusedLocalVariableInspection */
$startTime = floatval(0);
$startTime = gasStatic::doingTime();
$this->assertNotEquals(0, $startTime, __METHOD__ . __LINE__ . sprintf(ERROR_UT_EXPECTING_NON_ZERO_FP, $startTime));
$endTime = gasStatic::doingTime($startTime);
$this->assertNotEquals(0, $startTime, __METHOD__ . __LINE__ . sprintf(ERROR_UT_EXPECTING_NON_ZERO_FP, $endTime));
}
/**
* testNamasteReadBrokerInstantiation()
*
* this unit test creates a connection to the (primary) namaste read broker - which is an RPC broker and makes
* two basic requests -- so the first test is that we can connect to the RMQ queue that the broker is listening
* on.
*
* the second test is a ping request -- where we publish a ping event to the broker and await the response that
* the ping was received and responded to.
*
* the third test is a schema-fetch event request -- we publish a request to the broker requesting the schema
* report for the log template and test that we received the report for the correct template.
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 06-16-17 mks original coding
*
*/
public function testNamasteReadBrokerInstantiation()
{
$this->brokerClient = new gacBrokerClient(BROKER_QUEUE_R, basename(__FILE__) . COLON . __METHOD__ . COLON . __LINE__);
$this->assertTrue($this->brokerClient->status, __METHOD__ . __LINE__ . ERROR_BROKER_QUEUE_DECLARE . BROKER_QUEUE_R);
// this is an rpc-broker - so let's ping and get schema...
// set-up the broker request data
$meta = [
META_SYSTEM_NOTES => STRING_ORIGIN_UT,
META_CLIENT => CLIENT_UNIT,
META_SESSION_IP => STRING_SESSION_HOME
];
$request = [
BROKER_REQUEST => BROKER_REQUEST_PING,
BROKER_DATA => [],
BROKER_META_DATA => $meta
];
// publish the AMQP >PING< event request
$response = $this->brokerClient->call(gzcompress(json_encode($request))); // rpc queue
$response = json_decode(gzuncompress($response), true);
$this->assertTrue($response[PAYLOAD_STATUS], __METHOD__ . __LINE__ . ERROR_UT_EXPECTING_TRUE . PAYLOAD_STATUS);
// let's fetch the log table schema
$meta[META_TEMPLATE] = 'Logs';
$request = [
BROKER_REQUEST => BROKER_REQUEST_SCHEMA,
BROKER_DATA => [],
BROKER_META_DATA => $meta
];
$response = $this->brokerClient->call(gzcompress(json_encode($request))); // rpc queue
$response = json_decode(gzuncompress($response), true);
$this->assertTrue($response[PAYLOAD_STATUS], __METHOD__ . __LINE__ . ERROR_UT_BROKER_STATUS);
$this->assertEquals(COLLECTION_MONGO_LOGS, $response[PAYLOAD_RESULTS][TEMPLATE_FEATURE_TITLE], __METHOD__ . __LINE__ . COLON . 'error: expecting ' . COLLECTION_MONGO_LOGS . ' but received: ' . $response[PAYLOAD_RESULTS][TEMPLATE_FEATURE_TITLE]);
// deallocate the broker client
$this->brokerClient->__destruct();
unset($this->brokerClient);
}
/**
* testNamasteWriteBrokerInstantiation()
*
* this unit test creates a connection to the (primary) namaste write broker - which is an RPC broker and makes
* two basic requests -- so the first test is that we can connect to the RMQ queue that the broker is listening
* on.
*
* the second test is a ping request -- where we publish a ping event to the broker and await the response that
* the ping was received and responded to.
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 06-19-17 mks original coding
*
*/
public function testNamasteWriteBrokerInstantiation()
{
$this->brokerClient = new gacBrokerClient(BROKER_QUEUE_W, basename(__FILE__) . COLON . __METHOD__ . COLON . __LINE__);
$this->assertTrue($this->brokerClient->status, __METHOD__ . __LINE__ . ERROR_BROKER_QUEUE_DECLARE . BROKER_QUEUE_R);
// this is an rpc-broker - so let's ping and get schema...
// set-up the broker request data
$meta = [
META_SYSTEM_NOTES => STRING_ORIGIN_UT,
META_CLIENT => CLIENT_UNIT,
META_SESSION_IP => STRING_SESSION_HOME
];
$request = [
BROKER_REQUEST => BROKER_REQUEST_PING,
BROKER_DATA => [],
BROKER_META_DATA => $meta
];
// publish the AMQP >PING< event request
$response = $this->brokerClient->call(gzcompress(json_encode($request))); // rpc queue
$response = json_decode(gzuncompress($response), true);
$this->assertTrue($response[PAYLOAD_STATUS], __METHOD__ . __LINE__ . ERROR_UT_EXPECTING_TRUE . PAYLOAD_STATUS);
// deallocate the broker client
$this->brokerClient->__destruct();
unset($this->brokerClient);
}
/**
* testNamasteAdminInBrokerInstantiation()
*
* this unit test creates a connection to the AdminIn broker - which is a fire-n-forget broker and makes
* two basic requests -- so the first test is that we can connect to the RMQ queue that the broker is listening
* on.
*
* the second test is a ping request -- where we publish a ping event to the broker and await the response that
* the ping was received and responded to. Since the broker does not respond to pings, we're just testing that
* the adminIn broker class successfully published a message to the adminIn broker.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 06-19-17 mks original coding
*
*/
public function testNamasteAdminInBrokerInstantiation()
{
global $topDir;
$logDir = $topDir . DIR_LOGS;
$successMessage = 'successfully pinged broker: ga_admin_in_queue';
$this->brokerAdminInClient = new gacWorkQueueClient();
$this->assertTrue($this->brokerAdminInClient->status, __METHOD__ . __LINE__ . ERROR_BROKER_QUEUE_DECLARE . BROKER_QUEUE_R);
// this is an rpc-broker - so let's ping and get schema...
// set-up the broker request data
$meta = [
META_SYSTEM_NOTES => STRING_ORIGIN_UT,
META_CLIENT => CLIENT_UNIT,
META_SESSION_IP => STRING_SESSION_HOME
];
$request = [
BROKER_REQUEST => BROKER_REQUEST_PING,
BROKER_DATA => [],
BROKER_META_DATA => $meta
];
// publish the AMQP >PING< event request
$response = $this->brokerAdminInClient->call(gzcompress(json_encode($request))); // rpc queue
$this->assertTrue($response, __METHOD__ . __LINE__ . ERROR_UT_EXPECTING_TRUE . $response);
// grab the last line of the log file which should still be the output from the above request
$file = $logDir . SLASH . 'namaste.log';
$this->assertFileExists($file, ERROR_FILE_404 . $file);
$file = escapeshellarg($file);
sleep(1);
$line = `tail -n 1 $file`;
$this->assertNotFalse(strpos($line, $successMessage), sprintf(ERROR_STRING_404, $successMessage));
// deallocate the broker client
$this->brokerAdminInClient->__destruct();
unset($this->brokerAdminInClient);
}
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,897 @@
<?php
/**
* unit tests for the readBroker using a mongo data class
*
* each test block has relative comments.
*
*/
$_REDIRECT = false;
require(dirname(__DIR__) . '/../config/sneakerstrap.inc'); // and load the namaste environment
use PHPUnit\Framework\TestCase;
class readBrokerMongoTest extends TestCase
{
protected ?gacBrokerClient $readBrokerClient;
protected ?gacBrokerClient $adminOutClient;
protected static ?array $meta;
protected static int $maxRecordCount;
protected static int $totalRecordCount;
protected static string $eventGUID;
protected static ?array $adminMeta;
protected static string $recordGUID;
/**
* setUpBeforeClass() -- public static unit test method
*
* this method is called first, and once, on execution. It sets up a list of brokers we're going to test.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 07-27-17 mks original coding
* 10-19-17 mks CORE-610: maxRecordCount support
* 01-03-19 mks DB-78: auditing support
* 03-12-19 mks DB-116: updated for new cacheMapping
*
*/
public static function setUpBeforeClass()
{
parent::setUpBeforeClass();
// meta data
static::$meta = [
META_CLIENT => CLIENT_UNIT,
META_CLIENT_IP => STRING_SESSION_HOME,
META_SYSTEM_NOTES => STRING_ORIGIN_UT,
META_TEMPLATE => TEMPLATE_CLASS_TEST_MONGO
];
// max record count
static::$maxRecordCount = intval( gasConfig::$settings[CONFIG_DATABASE][CONFIG_DATABASE_QUERY_RECORD_LIMIT] );
// event GUID
static::$eventGUID = '';
// meta data for admin requests
static::$adminMeta = [
META_CLIENT => CLIENT_UNIT,
META_CLIENT_IP => STRING_SESSION_HOME,
META_SYSTEM_NOTES => STRING_ORIGIN_UT
];
}
/**
* setUp() -- unit test reserved method
*
* the setUp method is executed prior to each test - the method instantiates a new client connecting to the
* read broker.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 07-27-17 mks original coding
* 01-03-19 mks DB-78: added the adminOut client for testing audit
*
*/
protected function setUp()
{
// validate the meta data for the pending query
$this->assertTrue(!empty(static::$meta), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_META_404);
$this->assertTrue(is_array(static::$meta), (__FILE__ . COLON . __LINE__) . COLON . ERROR_META_INVALID_FORMAT_ARRAY);
$this->assertTrue(array_key_exists(META_TEMPLATE, static::$meta), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_META_KEY_404 . META_TEMPLATE);
$this->readBrokerClient = new gacBrokerClient(BROKER_QUEUE_R, basename(__FILE__) . COLON . __METHOD__ . COLON . __LINE__);
$this->assertTrue($this->readBrokerClient->status, __METHOD__ . __LINE__ . ERROR_BROKER_QUEUE_DECLARE . BROKER_QUEUE_R);
// create the admin broker client
$this->adminOutClient = new gacBrokerClient(BROKER_QUEUE_AO, basename(__FILE__) . COLON . __METHOD__ . COLON . __LINE__);
$this->assertTrue($this->adminOutClient->status, __FILE__ . COLON . __LINE__ . COLON . ERROR_BROKER_QUEUE_DECLARE . BROKER_QUEUE_AO);
}
/**
* tearDown() -- unit test method
*
* this is the (reserved) tearDown method which is executed at the end of every test.
* the method deletes the current broker client.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 07-27-17 mks original coding
*
*/
protected function tearDown()
{
$this->readBrokerClient->__destruct();
unset($this->readBrokerClient);
}
/**
* testTemplateReport() -- unit test method
*
* This method tests that we can (a) query the read-broker for a schema-fetch event and (b) that we receive
* a template report.
*
* There's no detailed testing of the report contents as contents are fluid while the framework is in development.
* However, this should be fleshed-out at a later date to test for fields specific to the PDO class in terms
* of their existence as defined in the mongo test class: gatTestMongo.class.inc.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 10-18-17 mks CORE:584: original coding
*
*/
public function testTemplateReport()
{
// set up the broker event request
$request = [
BROKER_REQUEST => BROKER_REQUEST_SCHEMA,
BROKER_DATA => null,
BROKER_META_DATA => static::$meta
];
// build the request payload and submit the request to the read broker
$payload = gzcompress(json_encode($request));
$response = $this->readBrokerClient->call($payload);
$response = json_decode(gzuncompress($response), true);
// validate: successful broker event
$this->assertTrue(is_array($response), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_MISSING_ARRAY . 'response payload');
// validate the status of the payload
$this->assertTrue($response[PAYLOAD_STATUS], (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_TRUE . 'not true');
}
/*
* testRandomFetch() -- unit test method
*
* in this first test, we're going to submit a null query to the read broker, but we're going to constrain the
* return data set by limiting the fetch to one record. Since we're using the test-class, caching is enabled,
* so we need to validate that a cache key was returned, and that the record was successfully cached in memory,
* and that the cached object matches the object in the $data property and that the calculated checksum matches
* the checksum value created when the object was cached.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 07-27-17 mks CORE-486: initial coding
* 01-02-19 mks DB-78: auditing support, memorizing guid values for the audit test
*
*/
public function testRandomFetch()
{
$query = null;
$metaCopy = static::$meta;
// limit the return data count to 1 record (we'll test for this...)
$metaCopy[META_LIMIT] = 1;
static::$eventGUID = guid(); // create our own system-event GUID for the audit validation
$metaCopy[META_EVENT_GUID] = static::$eventGUID;
$metaCopy[META_SYSTEM_NOTES] = basename(__METHOD__) . AT . __LINE__;
// set up the broker request
$request = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [STRING_QUERY_DATA => $query ],
BROKER_META_DATA => $metaCopy
];
// build the request payload and submit the request to the read broker
$payload = gzcompress(json_encode($request));
$response = $this->readBrokerClient->call($payload);
$response = json_decode(gzuncompress($response), true);
// validate: successful broker event
$this->assertTrue(is_array($response), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_MISSING_ARRAY . 'response payload');
// validate the status of the payload
$this->assertTrue($response[PAYLOAD_STATUS], (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_TRUE . 'not true');
// validate: return data has queryResults in payload
$this->assertTrue(array_key_exists(STRING_QUERY_RESULTS, $response[PAYLOAD_RESULTS]), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_KEY_404 . STRING_QUERY_RESULTS);
// validate one record was returned by counting the number of elements in the queryResults payload
$this->assertEquals(1, count($response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS]), (__FILE__ . COLON . __LINE__) . COLON . (sprintf(ERROR_DATA_RECORD_COUNT, 1, count($response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS]))));
// validate: return data has queryData in payload
$this->assertTrue(array_key_exists(STRING_QUERY_DATA, $response[PAYLOAD_RESULTS]), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_KEY_404 . STRING_QUERY_DATA);
// validate: we got the record returned count
$this->assertTrue(array_key_exists(STRING_REC_COUNT_RET, $response[PAYLOAD_RESULTS][STRING_QUERY_DATA]), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_KEY_404 . STRING_REC_COUNT_RET);
$recordsReturned = $response[PAYLOAD_RESULTS][STRING_QUERY_DATA][STRING_REC_COUNT_RET];
// validate the recCount is an integer
$this->assertTrue(is_int($recordsReturned), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_TYPE_MISMATCH . COLON . STRING_REC_COUNT_RET);
// validate the recCount is = 1 because that's what we ordered with META_LIMIT
$this->assertEquals(1, $recordsReturned, (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_RANGE . COLON . STRING_REC_COUNT_RET);
// validate that we got the total record count
$this->assertTrue(array_key_exists(STRING_REC_COUNT_TOT, $response[PAYLOAD_RESULTS][STRING_QUERY_DATA]), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_KEY_404 . STRING_REC_COUNT_TOT);
// validate that the total-rec-count is an integer
static::$totalRecordCount= intval($response[PAYLOAD_RESULTS][STRING_QUERY_DATA][STRING_REC_COUNT_TOT]);
$this->assertTrue(is_int(static::$totalRecordCount), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_TYPE_MISMATCH . STRING_REC_COUNT_TOT);
// validate that the total-rec count is > 0
$this->assertGreaterThan(0, static::$totalRecordCount, (__FILE__ . COLON . __LINE__ ) . COLON . ERROR_DATA_RANGE . STRING_REC_COUNT_TOT);
// extract the cacheKey
$cacheKey = $response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS][0];
// validate that we can fetch data from cache using the key
$record = gasCache::get($cacheKey);
$this->assertNotFalse($record, (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_TRUE . 'getCache::get(record)');
$record = (array) json_decode(gzuncompress($record), true);
// validate the checksum
$cksum = $record[STRING_CHECKSUM];
$rec = $record;
static::$recordGUID = $rec[0][STRING_KEY]; // copy off the record guid for the audit unit test
unset($rec[STRING_CHECKSUM]); // record is now back in it's original, pre-checksum, state
$dataCheckSum = md5(gzcompress(json_encode($rec)));
$this->assertEquals($cksum, $dataCheckSum, (__FILE__ . COLON . __LINE__) . COLON . ERROR_CACHE_DATA_CHECKSUM . $cacheKey);
unset(static::$meta[META_LIMIT]);
}
/**
* testAuditRecordCreateOnFetch() -- unit test method
*
* This unit test relies on the previous method: testRandomFetch() -- in testRandomFetch() we saved copies of the
* GUIDs (the GUID of the test record, and the pre-populated event GUID).
*
* This unit test validates both GUIDs and then builds a remoteFetch event query to the admin broker to fetch
* the audit record that should have been created from the fetch event using the guids as a unique query key.
*
* We test that this audit record as a EVENT_NAME_AUDIT_FETCH type event, once we've asserted that we were able
* to successfully retrieve the audit record specific to the event.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 01-03-18 mks DB-78: original coding
*
*/
public function testAuditRecordCreateOnFetch()
{
// sleep to give the audit record a chance to be written to disk
sleep(1);
// we need to have these two guids pre-stored for this test
$this->assertTrue(validateGUID(static::$eventGUID), (basename(__METHOD__) . COLON . __LINE__) . COLON . ERROR_EVENT_GUID_404);
$this->assertTrue(validateGUID(static::$recordGUID), (basename(__FILE__) . COLON . __LINE__) . COLON . ERROR_INVALID_GUID . static::$recordGUID);
// we should have created an audit record - build a remote-fetch request off the record token and the event GUID
// build the query to fetch the audit record from the admin service
$query = [
AUDIT_RECORD_TOKEN => [ OPERAND_NULL => [ OPERATOR_EQ => [ static::$recordGUID ]]],
DB_EVENT_GUID => [ OPERAND_NULL => [ OPERATOR_EQ => [ static::$eventGUID ]]],
OPERAND_AND => null
];
static::$adminMeta[META_TEMPLATE] = TEMPLATE_CLASS_AUDIT;
$request = [
BROKER_REQUEST => BROKER_REQUEST_REMOTE_FETCH,
BROKER_DATA => [ STRING_QUERY_DATA => $query ],
BROKER_META_DATA => static::$adminMeta
];
$payload = gzcompress(json_encode($request));
$response = $this->adminOutClient->call($payload);
$response = json_decode(gzuncompress($response), true);
$this->assertTrue($response[PAYLOAD_STATUS], __FILE__ . COLON . __LINE__ . COLON . sprintf(ERROR_UT_BROKER_EVENT_FAIL, BROKER_REQUEST_REMOTE_FETCH, $response[PAYLOAD_STATE]));
$operation = $response[PAYLOAD_RESULTS][PAYLOAD_QUERY][0][AUDIT_OPERATION . COLLECTION_MONGO_AUDIT_EXT];
$this->assertEquals(EVENT_NAME_AUDIT_FETCH, $operation, (basename(__FILE__) . COLON . __LINE__) . COLON . sprintf(ERROR_UT_VALS_NOT_EQUAL, EVENT_NAME_AUDIT_FETCH, $operation));
}
/**
* testNegativeRequest() -- unit test method
*
* this test submits a bad request to the read-broker and validates the return payload data. This test is to
* ensure that submitting an unknown event to the broker will be handled gracefully and will return sufficient
* information necessary to diagnosing why the request was rejected.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 07-28-17 mks CORE-486: original coding
*
*/
public function testNegativeRequest()
{
// set up a bad (non-existent request for this) broker request
$badEvent = BROKER_REQUEST_DELETE;
$request = [
BROKER_REQUEST => $badEvent,
BROKER_DATA => [STRING_QUERY_DATA => null ],
BROKER_META_DATA => static::$meta
];
// build the request payload and submit the request to the read broker
$payload = gzcompress(json_encode($request));
$response = $this->readBrokerClient->call($payload);
$response = json_decode(gzuncompress($response), true);
// validate that the return payload is an array
$this->assertTrue(is_array($response), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_MISSING_ARRAY . 'broker response');
// validate that we're returning all required array keys, even on a bad request
$this->assertArrayHasKey(PAYLOAD_STATUS, $response, (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_KEY_404 . PAYLOAD_STATUS);
$this->assertArrayHasKey(PAYLOAD_STATE, $response, (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_KEY_404 . PAYLOAD_STATE);
$this->assertArrayHasKey(PAYLOAD_DIAGNOSTICS, $response, (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_KEY_404 . PAYLOAD_DIAGNOSTICS);
$this->assertArrayHasKey(PAYLOAD_RESULTS, $response, (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_KEY_404 . PAYLOAD_RESULTS);
// validate that the bad request was acknowledged and rejected and that we've qualified the rejection
// as a bad-event for this broker
$this->assertFalse($response[PAYLOAD_STATUS], (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_FALSE . PAYLOAD_STATUS);
$this->assertEquals(STATE_DOES_NOT_EXIST, $response[PAYLOAD_STATE], (__FILE__ . COLON . __LINE__) . COLON . ERROR_INVALID_STATE . $response[PAYLOAD_STATE]);
$expectedResponse = ERROR_EVENT_404 . $badEvent;
$this->assertEquals($expectedResponse, $response[PAYLOAD_RESULTS], (__FILE__ . COLON . __LINE__) . COLON . sprintf(ERROR_UT_STRING_MISMATCH, $expectedResponse, $response[PAYLOAD_RESULTS]));
}
/**
* testNegativeFieldQuery() -- unit test method
*
* this unit test is another negative test - where we want the framework to reject (fail) a request. In this
* test, we're going to submit a query that uses an invalid column name for the data class. We'd expect the
* framework to reject the request and we test for the rejection.
*
*
* @author mike@givingassistant.org
* @version 1.0.
*
*
* HISTORY:
* ========
* 07-28-17 mks CORE-486: original coding
*
*/
public function testNegativeFieldQuery()
{
$badField = 'fieldDoesNotExist';
$query = [ $badField => [ OPERAND_NULL => [ OPERATOR_EQ => [1] ] ] ];
$request = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [STRING_QUERY_DATA => $query ],
BROKER_META_DATA => static::$meta
];
// build the request payload and submit the request to the read broker
$payload = gzcompress(json_encode($request));
$response = $this->readBrokerClient->call($payload);
$response = json_decode(gzuncompress($response), true);
// validate that the return payload is an array
$this->assertTrue(is_array($response), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_MISSING_ARRAY . 'broker response');
// validate that the broker returned a false (success) response
$this->assertFalse($response[PAYLOAD_STATUS], (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_FALSE . PAYLOAD_STATUS);
// validate that we returned a data error
$this->assertEquals(STATE_DATA_ERROR, $response[PAYLOAD_STATE], (__FILE__ . COLON . __LINE__) . COLON . ERROR_INVALID_STATE . $response[PAYLOAD_STATE]);
// validate the diagnostic message
$expectedResponse = sprintf(ERROR_QB_ATTRIBUTE_404, $badField, (STRING_CLASS_GAT . TEMPLATE_CLASS_TEST_MONGO));
$gotResponse = $response[PAYLOAD_DIAGNOSTICS][0];
$this->assertEquals($expectedResponse, $gotResponse, (__FILE__ . COLON . __LINE__) . COLON . sprintf(ERROR_UT_STRING_MISMATCH, $expectedResponse, $gotResponse));
}
/**
* testNegativeNIFQuery() -- unit test method
*
* this is a negative unit test - we coded this to fail. We want to submit a query with a predicate that
* contains a non-indexed field (NIF). One of the more-important features of Namaste is to evaluate and
* qualify query requests.
*
* Namaste does not allow query predicates with non-indexed fields and should reject these requests with a
* STATE_INDEX_ERROR state return.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 07-31-17 mks original coding
*
*/
public function testNegativeNIFQuery()
{
// legit query -- all values are = 1, but the field is not indexed so query should be rejected
$query = [ CM_TST_FIELD_TEST_NIF => [ OPERAND_NULL => [ OPERATOR_EQ => [1] ] ] ];
$request = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [STRING_QUERY_DATA => $query ],
BROKER_META_DATA => static::$meta
];
// build the request payload and submit the request to the read broker
$payload = gzcompress(json_encode($request));
$response = $this->readBrokerClient->call($payload);
$response = json_decode(gzuncompress($response), true);
// validate the response payload
$this->assertFalse($response[PAYLOAD_STATUS], (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_FALSE . PAYLOAD_STATUS);
$this->assertEquals(STATE_INDEX_ERROR , $response[PAYLOAD_STATE], (__FILE__ . COLON . __LINE__) . COLON . sprintf(ERROR_UT_FIELD_VALUE, PAYLOAD_STATE));
}
/**
* testNegativeInstantiation -- secret unit test
*
* this test has to be run manually -- in other words, it requires your setting the "enabled" toggle in the
* XML configuration under either the <databases> tag, or under <databases><dbSchema> tags to 0 to force the error.
*
* This has to be done before the brokers are started because once the configuration is loaded, you can't toggle
* it off manually in the code -- in other words the test-class configuration tweak does not affect the broker
* configuration.
*
* Test outputs were stored in the jira ticket.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 08-03-17 mks CORE-503: original coding
*
*/
// public function testNegativeInstantiation()
// {
//
// // generic fetch-all query
// $request = [
// BROKER_REQUEST => BROKER_REQUEST_FETCH,
// BROKER_DATA => [STRING_QUERY_DATA => null ],
// BROKER_META_DATA => static::$meta
// ];
//
// // build the request payload and submit the request to the read broker
// $payload = gzcompress(json_encode($request));
// $response = $this->readBrokerClient->call($payload);
// $response = json_decode(gzuncompress($response), true);
//
// $x = 1 ;
// }
/**
* testFetchAll() -- unit test method
*
* this test is going to launch a null-query test. For this test to be successfully evaluated, you must have more
* records in the database than the queryRecordLimit set in the XML configuration.
*
* we're launching a "get all the records" query without a limit clause in an attempt at fetching all the records
* in a collection. This is a very bad thing if your collection has a hundred-million rows, or more, of data.
*
* the namaste xml file limits the number of records returned in any given fetch query. When we submit a null
* query, we're not including the limit-value in the meta payload -- this should tell the framework to fetch all
* the collection's records.
*
* the framework should self-impose the record limit and that limit should be the value configured in the xml.
* we're going to test for that value as the number of records returned.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 07-28-17 mks CORE-486: original coding
*
*/
public function testFetchAll()
{
$recordLimit = gasConfig::$settings[CONFIG_DATABASE][CONFIG_DATABASE_QUERY_RECORD_LIMIT];
$request = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [STRING_QUERY_DATA => null ],
BROKER_META_DATA => static::$meta
];
// build the request payload and submit the request to the read broker
$payload = gzcompress(json_encode($request));
$response = $this->readBrokerClient->call($payload);
$response = json_decode(gzuncompress($response), true);
// validate that the return payload is an array
$this->assertTrue(is_array($response), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_MISSING_ARRAY . 'broker response');
// validate that the payload returned was successful
$this->assertTrue($response[PAYLOAD_STATUS], (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_TRUE . PAYLOAD_STATUS);
// validate that we returned the current-configured max-number of records
$recsReturned = $response[PAYLOAD_RESULTS][STRING_QUERY_DATA][STRING_REC_COUNT_RET];
$msg = sprintf(ERROR_UT_INTEGER_MISMATCH, $recordLimit, $recsReturned, STRING_REC_COUNT_RET);
$this->assertEquals($recordLimit, $recsReturned, (__FILE__ . COLON . __LINE__) . COLON . $msg);
}
/**
* testSkipLimit() -- unit test method
*
* this method validates the skip-limit processing accuracy for the framework.
*
* First, we're going to generate a random number that's equal to 25% of the total record count, +/- 10.
* Next, exec a query that returns a list of 100 sorted guids, starting with the offset we just calculated
* Next, generate a random number between 0 and 9 (1-10) for the search discriminant
* Next, save the sorted list of guids to an array
* Next, exec a query that pulls that record (starting offset + rand-number) from the db
* Last, compare the single returned value against the value in the list stored at the calculated offset
*
* I tried to limit the number of assertions in this test based on if the same assertions had been previously
* tested in preceding methods.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 07-31-17 mks CORE-486: original coding
* 10-19-17 mks CORE-610: refactored for "new" caching schema, etc.
* 03-14-18 mks CORE-833: adjusted testInteger field range to match what's being generated in the
* test classes (1-20) NOT (1-100). Ensure we return a lot of records by limiting
* the integer value to 1/2 of the ranged maximum.
*/
public function testSkipLimit()
{
$this->assertGreaterThan(0, static::$maxRecordCount, sprintf(ERROR_UT_FIELD_VALUE, 'maxRecordCount'));
// build a query: fetch all records with the boolean field set to true and the status field = active
// point is to build a query that fetches a significant number of records...
$query = [
CM_TST_FIELD_TEST_INT => [OPERAND_NULL => [OPERATOR_GT => [mt_rand(0, 9)]]],
CM_TST_FIELD_TEST_STATUS => [OPERAND_NULL => [OPERATOR_EQ => [STATUS_ACTIVE]]],
OPERAND_AND => null
];
// build the sort and projection arrays so we can test these options:
$sort = [CM_TST_TOKEN => STRING_SORT_ASC]; // sort by data-created ascending
$projection = [CM_TST_TOKEN]; // return a list of record guids
// build the request
$request = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [
STRING_QUERY_DATA => $query,
STRING_SORT_DATA => $sort,
STRING_RETURN_DATA => $projection
],
BROKER_META_DATA => static::$meta
];
// launch the query and let's pull out the token list
$payload = gzcompress(json_encode($request));
$response = $this->readBrokerClient->call($payload);
$response = json_decode(gzuncompress($response), true);
// validate that the return payload is an array
$this->assertTrue(is_array($response), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_MISSING_ARRAY . 'broker response');
// validate that the payload returned was successful
$this->assertTrue($response[PAYLOAD_STATUS], (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_TRUE . PAYLOAD_STATUS);
// get a list of the testInteger_tst aggregation:
// db.gaTest_tst.aggregate([{ $group: {_id: "$testInteger_tst", count:{$sum:1}}}])
// save a copy of the sorted record list - this because our validation authority
$cacheGUID = $response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS][0];
$this->assertTrue(validateGUID(str_replace(gasConfig::$settings[CONFIG_ID][CONFIG_ID_ENV] . UDASH, '', $cacheGUID)), (__FILE__ . COLON . __LINE__) . ERROR_UT_CACHE_FETCH_FAIL);
$recordList = json_decode(gzuncompress(gasCache::get($cacheGUID)), true);
if (array_key_exists(STRING_CHECKSUM, $recordList)) unset($recordList[STRING_CHECKSUM]);
$this->assertTrue(count($recordList) <= static::$maxRecordCount, (__FILE__ . COLON . __LINE__) . COLON . sprintf(ERROR_DATA_ARRAY_COUNT_EXCESSIVE, count($recordList), static::$maxRecordCount));
// now - generate a new query to extract a random record within that range
$recCount = count($recordList);
$randomRecord = intval(mt_rand($recCount / 4, $recCount));
static::$meta[META_SKIP] = $randomRecord;
static::$meta[META_LIMIT] = 1; // and retrieve only that record
// build the request
$request = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [
STRING_QUERY_DATA => $query,
STRING_SORT_DATA => $sort,
STRING_RETURN_DATA => $projection
],
BROKER_META_DATA => static::$meta
];
// submit the request and validate the payload return
$payload = gzcompress(json_encode($request));
$response = $this->readBrokerClient->call($payload);
$response = json_decode(gzuncompress($response), true);
// validate that the return payload is an array
$this->assertTrue(is_array($response), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_MISSING_ARRAY . 'broker response');
// validate that the payload returned was successful
$this->assertTrue($response[PAYLOAD_STATUS], (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_TRUE . PAYLOAD_STATUS);
$this->assertTrue(is_array($response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS]), (__FILE__ . COLON . __LINE__ . COLON) . ERROR_UT_EMPTY_RESULTS);
// get the record cache key and fetch from cache
$newRecord = $response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS][0];
$newRecord = json_decode(gzuncompress(gasCache::get($newRecord)), true);
$newRecordGuid = $newRecord[0][STRING_KEY];
$oldRecGuid = $recordList[$randomRecord][STRING_KEY];
$this->assertNotFalse(strpbrk($oldRecGuid, $cacheGUID), (__FILE__ . COLON . __LINE__) . COLON . sprintf(ERROR_UT_VALS_NOT_EQUAL, $newRecordGuid, $oldRecGuid));
}
/**
* testNonCachedFetch() -- public unit test method
*
* The purpose of this unit test is to publish a fetch event request using the META_DONUT_FILTER flag in the meta
* data payload. We're submitting the request and limiting the fetch to be a single record.
*
* We're injecting the META_DONUT_FILTER as part of the meta-data payload to force the request to return the
* record containing the actual schema.
*
* The validation comes when we fetch the token from the record payload - each record is required to have one - and
* the act of isolating that record involves querying by the class extension: implicit proof that we fetched
* the pure version of the record.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 05-23-19 mks DB-40: unit-tests for non-cached data classes: original coding
*
*/
public function testNonCachedFetch()
{
$query = null;
$metaCopy = static::$meta;
// limit the return data count to 1 record (we'll test for this...)
$metaCopy[META_LIMIT] = 1;
static::$eventGUID = guid(); // create our own system-event GUID for the audit validation
$metaCopy[META_EVENT_GUID] = static::$eventGUID;
$metaCopy[META_SYSTEM_NOTES] = basename(__METHOD__) . AT . __LINE__;
$metaCopy[META_DO_CACHE] = false; // don't filter the return payload
// set up the broker request
$request = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [STRING_QUERY_DATA => $query ],
BROKER_META_DATA => $metaCopy
];
$payload = gzcompress(json_encode($request));
$response = $this->readBrokerClient->call($payload);
$response = json_decode(gzuncompress($response), true);
// validate that the return payload is an array
$this->assertTrue(is_array($response), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_MISSING_ARRAY . 'broker response');
// validate that the payload returned was successful
$this->assertTrue($response[PAYLOAD_STATUS], (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_TRUE . PAYLOAD_STATUS);
$tok = $response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS][0][STRING_KEY];
$this->assertTrue(validateGUID($tok), basename(__METHOD__) . AT . __LINE__ . COLON . ERROR_INVALID_GUID . $tok);
}
/**
* testSubCollectionBasicFetch() -- public unit test method
*
* This unit test evaluates the (relatively) new function for fetching a record based on a sub-collection record.
* (Note: sub-collection operations are only supported on the mongoDB schema.)
* Under the mongoDB schema, when you have a sub-Collection column, all fields in the sub-collection are
* automatically indexed. This means you can index-search on any column within the sub-collection record. This
* unit test, then, makes the following in-method assertions:
*
* - that we can successfully submit a sub-collection query request to the read broker
* - that the sub-collection request returned data
* - that the sub-collection request returned one record (we set the meta limit)
* - that the sub-collection integer value matches the discriminate-search value
*
* We begin by setting an arbitrary integer value for the search key then tweaking the meta data so that we limit
* the return data set to a single record and bypass cache.
*
* The query is built, submitted, the response consumed and unpacked and then tested according to the above
* listed requirements.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 04-14-20 mks ECI-107: original coding
*
*/
public function testSubCollectionBasicFetch()
{
$searchValue = 7; // whatever works
$metaCopy = static::$meta;
$metaCopy[META_LIMIT] = 1;
$metaCopy[META_SYSTEM_NOTES] = basename(__METHOD__) . AT . __LINE__;
$metaCopy[META_DO_CACHE] = false; // don't filter the return payload
// build a simple request querying against a single sub-collection field
$requestData = [
STRING_SUBC_COL => CM_TST_FIELD_TEST_SUBC,
STRING_SUBC_DATA => [ CM_TST_FIELD_TEST_INT => $searchValue]
];
$payload = [
BROKER_REQUEST => BROKER_REQUEST_SUBC_FETCH,
BROKER_DATA => $requestData,
BROKER_META_DATA => $metaCopy
];
$request = gzcompress(json_encode($payload));
$response = json_decode(gzuncompress($this->readBrokerClient->call($request)), true);
// validate the return payload - query was successful
$this->assertTrue($response[PAYLOAD_STATUS], basename(__FILE__) . AT . __LINE__ . COLON . ERROR_UT_EXPECTING_TRUE . PAYLOAD_STATUS);
// query returned data
$this->assertTrue(is_array($response[PAYLOAD_RESULTS]), basename(__METHOD__) . AT . __LINE__ . COLON . ERROR_DATA_ARRAY_NOT_ARRAY . PAYLOAD_RESULTS);
$this->assertTrue(is_array($response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS]), basename(__METHOD__) . AT . __LINE__ . COLON . ERROR_DATA_ARRAY_NOT_ARRAY . STRING_QUERY_RESULTS);
$recCount = count($response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS]);
$subCRecord = $response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS][0][CM_TST_FIELD_TEST_SUBC][0];
// query returned the correct amount of data
$this->assertEquals(1, $recCount, basename(__METHOD__) . AT . __LINE__ . COLON . sprintf(ERROR_DATA_ARRAY_COUNT, 1, STRING_QUERY_RESULTS, $recCount));
// search discriminant value is present in the returned data
$this->assertEquals($searchValue, $subCRecord[CM_TST_FIELD_TEST_INT], basename(__METHOD__) . AT . __LINE__ . COLON . sprintf(ERROR_UT_FIELD_VALUE, CM_TST_FIELD_TEST_INT) . COLON . $subCRecord[CM_TST_FIELD_TEST_INT]);
}
/**
* testSubCollectionAdvancedFetch() -- unit test method
*
* This unit test method is basically a copy of the above test with the notable difference being the query that
* we're submitting. The point of this test is to show that we can submit a complex (more than one query
* discriminant) query on a sub-collection to return a record. As in the previous test, this method makes the
* following assertions:
*
* - that we can successfully submit a sub-collection query request to the read broker
* - that the sub-collection request returned data
* - that the sub-collection request returned one record (we set the meta limit)
* - that the sub-collection integer value matches the discriminate-search value
*
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 04-15-20 mks ECI-107: original coding
*
*/
public function testSubCollectionAdvancedFetch()
{
$intSearchValue = 7; // doesn't matter
$boolSearchValue = true; // still doesn't matter
$metaCopy = static::$meta;
$metaCopy[META_LIMIT] = 1;
$metaCopy[META_SYSTEM_NOTES] = basename(__METHOD__) . AT . __LINE__;
$metaCopy[META_DO_CACHE] = false; // don't filter the return payload
// build a simple request querying against a single sub-collection field
$requestData = [
STRING_SUBC_COL => CM_TST_FIELD_TEST_SUBC,
STRING_SUBC_DATA => [ CM_TST_FIELD_TEST_INT => $intSearchValue,
CM_TST_FIELD_TEST_BOOL => $boolSearchValue]
];
$payload = [
BROKER_REQUEST => BROKER_REQUEST_SUBC_FETCH,
BROKER_DATA => $requestData,
BROKER_META_DATA => $metaCopy
];
$request = gzcompress(json_encode($payload));
$response = json_decode(gzuncompress($this->readBrokerClient->call($request)), true);
// validate the return payload - query was successful
$this->assertTrue($response[PAYLOAD_STATUS], basename(__FILE__) . AT . __LINE__ . COLON . ERROR_UT_EXPECTING_TRUE . PAYLOAD_STATUS);
// query returned data
$this->assertTrue(is_array($response[PAYLOAD_RESULTS]), basename(__METHOD__) . AT . __LINE__ . COLON . ERROR_DATA_ARRAY_NOT_ARRAY . PAYLOAD_RESULTS);
$this->assertTrue(is_array($response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS]), basename(__METHOD__) . AT . __LINE__ . COLON . ERROR_DATA_ARRAY_NOT_ARRAY . STRING_QUERY_RESULTS);
$recCount = count($response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS]);
$subCRecord = $response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS][0][CM_TST_FIELD_TEST_SUBC][0];
// query returned the correct amount of data
$this->assertEquals(1, $recCount, basename(__METHOD__) . AT . __LINE__ . COLON . sprintf(ERROR_DATA_ARRAY_COUNT, 1, STRING_QUERY_RESULTS, $recCount));
// search discriminant value is present in the returned data
$this->assertEquals($intSearchValue, $subCRecord[CM_TST_FIELD_TEST_INT], basename(__METHOD__) . AT . __LINE__ . COLON . sprintf(ERROR_UT_FIELD_VALUE, CM_TST_FIELD_TEST_INT) . COLON . $subCRecord[CM_TST_FIELD_TEST_INT]);
}
/**
* testSubCollectionBadFetch() -- unit test method
*
* This method is a negative test; we're testing that the submitted event request will fail. The point of this
* test is to replicate an anticipated common problem - submitting a regular query to the sub-collection fetch.
* This should result in a rejection from the read-broker and that leads us to the only assertion native to
* the method:
*
* -- assert that the return payload has a false status b/c of the bad request submitted
*
* The request we'll submit is a valid fetch request that, were it submitted as a BROKER_REQUEST_FETCH event, would
* return a NOT_FOUND state because we've generated the search GUID ad-hoc.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 04-15-20 mks ECI-107: original coding
*
*/
public function testSubCollectionBadFetch()
{
$metaCopy = static::$meta;
$metaCopy[META_LIMIT] = 1;
$metaCopy[META_SYSTEM_NOTES] = basename(__METHOD__) . AT . __LINE__;
$metaCopy[META_DO_CACHE] = false; // don't filter the return payload
// build a "normal" query request instead of a sub-collection fetch - which should generate an error
$requestData = [
CM_TST_TOKEN => [ OPERAND_NULL => [ OPERATOR_EQ => [ guid() ]]]
];
$payload = [
BROKER_REQUEST => BROKER_REQUEST_SUBC_FETCH,
BROKER_DATA => $requestData,
BROKER_META_DATA => $metaCopy
];
$request = gzcompress(json_encode($payload));
$response = json_decode(gzuncompress($this->readBrokerClient->call($request)), true);
// validate the return payload - query was NOT successful
$this->assertFalse($response[PAYLOAD_STATUS], basename(__FILE__) . AT . __LINE__ . COLON . ERROR_UT_EXPECTING_FALSE . PAYLOAD_STATUS);
}
/**
* testSubCollectionBadFieldFetch() -- unit test method
*
* This unit test is for ensuring that names of query discriminants in the sub-collection are valid (exists). The
* method will submit a query to the fetch-subC event using a field name, in the sub-collection, that is not defined
* as such in the sub-collection definition within the template file. As such, the method makes the following
* assertion:
*
* - that the request fails because the search field DNE in the sub-collection definition
*
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 04-15-20 ECI-107: original coding
*
*/
public function testSubCollectionBadFieldFetch()
{
$searchValue = 7; // whatever works
$metaCopy = static::$meta;
$metaCopy[META_LIMIT] = 1;
$metaCopy[META_SYSTEM_NOTES] = basename(__METHOD__) . AT . __LINE__;
$metaCopy[META_DO_CACHE] = false; // don't filter the return payload
// build a simple request querying against a single sub-collection field
$requestData = [
STRING_SUBC_COL => CM_TST_FIELD_TEST_SUBC,
STRING_SUBC_DATA => [ CM_STATUS => $searchValue] // <-- this key is not a valid sub-collection member
];
$payload = [
BROKER_REQUEST => BROKER_REQUEST_SUBC_FETCH,
BROKER_DATA => $requestData,
BROKER_META_DATA => $metaCopy
];
$request = gzcompress(json_encode($payload));
$response = json_decode(gzuncompress($this->readBrokerClient->call($request)), true);
// validate the return payload - query was successful
$this->assertFalse($response[PAYLOAD_STATUS], basename(__FILE__) . AT . __LINE__ . COLON . ERROR_UT_EXPECTING_TRUE . PAYLOAD_STATUS);
}
}

View File

@@ -0,0 +1,608 @@
<?php
/**
* unit tests for the read broker using PDO data class
*
* each test block has relative comments
*
* Note: A lot of these tests are closely-duplicated from the tests in readBrokerMongoTest.php which is as it should
* be as the framework purports to be schema-agnostic... using duplicated tests (I've tweaked some values for templates
* and fields because we're working with a different test-class) should, by intent and design, prove this to be true.
*
* Note: queries will increase in complexity starting with a simple select and then eventually ending up with a query
* similar (or identical) to:
*
* SELECT createdDate_tst, count(*), status_tst, testInteger_tst
* FROM gaTest_tst
* GROUP BY testInteger_tst
* HAVING testBoolean_tst = 1
* ORDER BY createdDate_tst DESC
*
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 10-11-17 mks CORE-584: original coding
* 01-17-19 mks DB-105: updated for audit testing support
* 03-13-19 mks DB-116: updated for the new cacheMapping
*
*/
$_REDIRECT = false;
require(dirname(__DIR__) . '/../config/sneakerstrap.inc'); // and load the namaste environment
use PHPUnit\Framework\TestCase;
class readBrokerPDOTest extends TestCase
{
protected ?gacBrokerClient $readBrokerClient;
protected ?gacBrokerClient $adminOutClient;
protected static ?array $meta;
protected static ?array $adminMeta;
// protected static $keys;
protected static int $maxRecordCount;
protected static int $totalRecordCount;
protected static string $dataKey;
protected static string $eventKey;
/**
* setUpBeforeClass() -- public static unit test method
*
* this method is called first, and once, on execution. It sets up a list of brokers we're going to test.
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 10-11-17 mks original coding
*
*/
public static function setUpBeforeClass()
{
parent::setUpBeforeClass();
// meta data
static::$meta = [
META_CLIENT => CLIENT_UNIT,
META_CLIENT_IP => STRING_SESSION_HOME,
META_SYSTEM_NOTES => STRING_ORIGIN_UT,
META_TEMPLATE => TEMPLATE_CLASS_TEST_PDO
];
// meta data for admin requests
static::$adminMeta = [
META_CLIENT => CLIENT_UNIT,
META_CLIENT_IP => STRING_SESSION_HOME,
META_SYSTEM_NOTES => STRING_ORIGIN_UT
];
// max record count
static::$maxRecordCount = gasConfig::$settings[CONFIG_DATABASE][CONFIG_DATABASE_QUERY_RECORD_LIMIT];
}
/**
* setUp() -- unit test reserved method
*
* the setUp method is executed prior to each test - the method instantiates a new client connecting to the
* read broker.
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 10-11-17 mks CORE:584: original coding
* 01-17-19 mks DB-105: support for audit/journal testing
*
*/
protected function setUp()
{
// validate the meta data for the pending query
$this->assertTrue(!empty(static::$meta), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_META_404);
$this->assertTrue(is_array(static::$meta), (__FILE__ . COLON . __LINE__) . COLON . ERROR_META_INVALID_FORMAT_ARRAY);
$this->assertTrue(array_key_exists(META_TEMPLATE, static::$meta), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_META_KEY_404 . META_TEMPLATE);
$this->readBrokerClient = new gacBrokerClient(BROKER_QUEUE_R, basename(__FILE__) . COLON . __METHOD__ . COLON . __LINE__);
$this->assertTrue($this->readBrokerClient->status, __METHOD__ . __LINE__ . ERROR_BROKER_QUEUE_DECLARE . BROKER_QUEUE_R);
// create the admin broker client
$this->adminOutClient = new gacBrokerClient(BROKER_QUEUE_AO, basename(__FILE__) . COLON . __METHOD__ . COLON . __LINE__);
$this->assertTrue($this->adminOutClient->status, __FILE__ . COLON . __LINE__ . COLON . ERROR_BROKER_QUEUE_DECLARE . BROKER_QUEUE_AO);
}
/**
* tearDown() -- unit test method
*
* this is the (reserved) tearDown method which is executed at the end of every test.
* the method deletes the current broker client.
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 10-11-17 mks CORE:584: original coding
*
*/
protected function tearDown()
{
/** @noinspection PhpUndefinedMethodInspection */
$this->readBrokerClient->__destruct();
unset($this->readBrokerClient);
}
/**
* testTemplateReport() -- unit test method
*
* This method tests that we can (a) query the read-broker for a schema-fetch event and (b) that we receive
* a template report.
*
* There's no detailed testing of the report contents as contents are fluid while the framework is in development.
* However, this should be fleshed-out at a later date to test for fields specific to the PDO class in terms
* of their existence as defined in the PDO test class: gatTestPDO.class.inc.
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 10-18-17 mks CORE:584: original coding
*
*/
public function testTemplateReport()
{
// set up the broker event request
$request = [
BROKER_REQUEST => BROKER_REQUEST_SCHEMA,
BROKER_DATA => null,
BROKER_META_DATA => static::$meta
];
// build the request payload and submit the request to the read broker
$payload = gzcompress(json_encode($request));
$response = $this->readBrokerClient->call($payload);
$response = json_decode(gzuncompress($response), true);
// validate: successful broker event
$this->assertTrue(is_array($response), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_MISSING_ARRAY . 'response payload');
// validate the status of the payload
$this->assertTrue($response[PAYLOAD_STATUS], (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_TRUE . 'not true');
}
/*
* testRandomFetch() -- unit test method
*
* in this first test, we're going to submit a null query to the read broker, but we're going to constrain the
* return data set by limiting the fetch to one record. Since we're using the test-class, caching is enabled,
* so we need to validate that a cache key was returned, and that the record was successfully cached in memory,
* and that the cached object matches the object in the $data property and that the calculated checksum matches
* the checksum value created when the object was cached.
*
* This is the simplest query we can submit to the broker.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 10-11-17 mks CORE:584: original coding, ported for PDO from mongo
* 01-17-19 mks DB-105: support for audit/journal testing
* 10-09-19 mks DB-136: edge-case test for no test records in the db
*
*/
public function testRandomFetch()
{
$query = null;
// limit the return data count to 1 record (we'll test for this...)
$meta = static::$meta;
$meta[META_LIMIT] = 1;
static::$eventKey = guid();
$this->assertTrue(validateGUID(static::$eventKey), basename(__FILE__) . COLON . __LINE__ . COLON . ERROR_INVALID_GUID . static::$eventKey);
$meta[META_EVENT_GUID] = static::$eventKey; // use a pre-generated guid for the query in the next method test
// set up the broker request
$request = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [STRING_QUERY_DATA => $query ],
BROKER_META_DATA => $meta
];
// build the request payload and submit the request to the read broker
$payload = gzcompress(json_encode($request));
$response = $this->readBrokerClient->call($payload);
$response = json_decode(gzuncompress($response), true);
// validate: successful broker event
$this->assertTrue(is_array($response), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_MISSING_ARRAY . 'response payload');
// validate the status of the payload
$this->assertTrue($response[PAYLOAD_STATUS], (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_TRUE . 'not true');
// validate: return data has queryResults in payload
$this->assertTrue(array_key_exists(STRING_QUERY_RESULTS, $response[PAYLOAD_RESULTS]), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_KEY_404 . STRING_QUERY_RESULTS);
// if $response[results][queryResults] is null - there's no data in the db and doing this test is pointless
if (is_null($response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS])) {
echo basename(__METHOD__) . AT . __LINE__ . COLON . PHP_EOL;
echo 'Your table has no records to fetch - have you populated the table with test data?' . PHP_EOL;
exit(1);
}
// validate one record was returned by counting the number of elements in the queryResults payload
$this->assertEquals(1, count($response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS]), (__FILE__ . COLON . __LINE__) . COLON . (sprintf(ERROR_DATA_RECORD_COUNT, 1, count($response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS]))));
// validate: return data has queryData in payload
$this->assertTrue(array_key_exists(STRING_QUERY_DATA, $response[PAYLOAD_RESULTS]), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_KEY_404 . STRING_QUERY_DATA);
// validate: we got the record returned count
$this->assertTrue(array_key_exists(STRING_REC_COUNT_RET, $response[PAYLOAD_RESULTS][STRING_QUERY_DATA]), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_KEY_404 . STRING_REC_COUNT_RET);
$recordsReturned = $response[PAYLOAD_RESULTS][STRING_QUERY_DATA][STRING_REC_COUNT_RET];
// validate the recCount is an integer
$this->assertTrue(is_int($recordsReturned), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_TYPE_MISMATCH . COLON . STRING_REC_COUNT_RET);
// validate the recCount is = 1 because that's what we ordered with META_LIMIT
$this->assertEquals(1, $recordsReturned, (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_RANGE . COLON . STRING_REC_COUNT_RET);
// validate that we got the total record count
$this->assertTrue(array_key_exists(STRING_REC_COUNT_TOT, $response[PAYLOAD_RESULTS][STRING_QUERY_DATA]), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_KEY_404 . STRING_REC_COUNT_TOT);
// validate that the total-rec-count is an integer
static::$totalRecordCount = $response[PAYLOAD_RESULTS][STRING_QUERY_DATA][STRING_REC_COUNT_TOT];
$this->assertTrue(is_int(static::$totalRecordCount), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_TYPE_MISMATCH . STRING_REC_COUNT_TOT);
// validate that the total-rec count is > 0
$this->assertGreaterThan(0, static::$totalRecordCount, (__FILE__ . COLON . __LINE__ ) . COLON . ERROR_DATA_RANGE . STRING_REC_COUNT_TOT);
// extract the cacheKey
$cacheKey = $response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS][0];
// validate that we can fetch data from cache using the key
$record = gasCache::get($cacheKey);
$this->assertNotFalse($record, (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_TRUE . 'getCache::get(record)');
$record = (array) json_decode(gzuncompress($record), true);
// validate the checksum
$cksum = $record[STRING_CHECKSUM];
$rec = $record;
unset($rec[STRING_CHECKSUM]); // record is now back in it's original, pre-checksum, state
$dataCheckSum = md5(gzcompress(json_encode($rec)));
$this->assertEquals($cksum, $dataCheckSum, (__FILE__ . COLON . __LINE__) . COLON . ERROR_CACHE_DATA_CHECKSUM . $cacheKey);
static::$dataKey = $record[0][STRING_KEY];
// save the data key for the next test method
$this->assertTrue(validateGUID(static::$dataKey), basename(__FILE__) . COLON . __LINE__ . COLON . ERROR_INVALID_GUID . static::$dataKey);
}
/**
* testFetchAudit() -- unit test method
*
* This unit test verifies that the read event successfully created an audit record for the create event. When
* we query the admin database to fetch the audit record, the search is filtered by the record (data) guid and the
* event guid that was manually created during the new-record-create event.
*
* The following assertions are made:
*
* 1-2: that data saved in previous methods is intact and available
* 3: that the published broker event to fetch the audit record processed successfully
* 4: that the audit record shows the event to be a record-accessed event
*
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 01-17-19 mks DB-105: original coding
*
*/
public function testFetchAudit()
{
// pause for a second to allow the audit record to be written
sleep(1);
// test that we still have (saved) the two keys we need for this method's query
$this->assertTrue(validateGUID(static::$eventKey), basename(__FILE__) . COLON . __LINE__ . COLON . ERROR_INVALID_GUID . static::$eventKey);
$this->assertTrue(validateGUID(static::$dataKey), basename(__FILE__) . COLON . __LINE__ . COLON . ERROR_INVALID_GUID . static::$dataKey);
// build a fetch event request to get the audit record
$meta = static::$adminMeta;
$meta[META_TEMPLATE] = TEMPLATE_CLASS_AUDIT;
$query = [
AUDIT_RECORD_TOKEN => [ OPERAND_NULL => [ OPERATOR_EQ => [ static::$dataKey ]]],
DB_EVENT_GUID => [ OPERAND_NULL => [ OPERATOR_EQ => [ static::$eventKey ]]],
OPERAND_AND => null
];
$request = [
BROKER_REQUEST => BROKER_REQUEST_REMOTE_FETCH,
BROKER_DATA => [ STRING_QUERY_DATA => $query ],
BROKER_META_DATA => $meta
];
// submit the event request
$response = json_decode(gzuncompress($this->adminOutClient->call(gzcompress(json_encode($request)))), true);
$this->assertTrue($response[PAYLOAD_STATUS], basename(__FILE__) . COLON . __LINE__ . COLON . sprintf(ERROR_UT_BROKER_EVENT_FAIL, BROKER_REQUEST_REMOTE_FETCH, $response[PAYLOAD_STATE]));
$operation = $response[PAYLOAD_RESULTS][PAYLOAD_QUERY][0][AUDIT_OPERATION . COLLECTION_MONGO_AUDIT_EXT];
$this->assertEquals(EVENT_NAME_AUDIT_FETCH, $operation, (basename(__FILE__) . COLON . __LINE__) . COLON . sprintf(ERROR_UT_VALS_NOT_EQUAL, EVENT_NAME_AUDIT_FETCH, $operation));
}
/**
* testNegativeFieldQuery() -- unit test method
*
* this unit test is a negative test - we want the framework to reject (fail) a request. In this test, we're
* going to submit a query that uses an invalid column name for the data class. We'd expect the framework to
* reject the request and we test for that rejection.
*
* @author mike@givingassistant.org
* @version 1.0.
*
* HISTORY:
* ========
* 10-11-17 mks CORE:584: original coding, ported for PDO from mongo test
*
*/
public function testNegativeFieldQuery()
{
$badField = 'fieldDoesNotExist';
$query = [ $badField => [ OPERAND_NULL => [ OPERATOR_EQ => [1] ] ] ];
$request = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [STRING_QUERY_DATA => $query ],
BROKER_META_DATA => static::$meta
];
// build the request payload and submit the request to the read broker
$payload = gzcompress(json_encode($request));
$response = $this->readBrokerClient->call($payload);
$response = json_decode(gzuncompress($response), true);
// validate that the return payload is an array
$this->assertTrue(is_array($response), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_MISSING_ARRAY . 'broker response');
// validate that the broker returned a false (success) response
$this->assertFalse($response[PAYLOAD_STATUS], (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_FALSE . PAYLOAD_STATUS);
// validate that we returned a data error
$this->assertEquals(STATE_DATA_ERROR, $response[PAYLOAD_STATE], (__FILE__ . COLON . __LINE__) . COLON . ERROR_INVALID_STATE . $response[PAYLOAD_STATE]);
// validate the diagnostic message
$expectedResponse = sprintf(ERROR_QB_ATTRIBUTE_404, $badField, (STRING_CLASS_GAT . TEMPLATE_CLASS_TEST_PDO));
$gotResponse = $response[PAYLOAD_DIAGNOSTICS][0];
$this->assertEquals($expectedResponse, $gotResponse, (__FILE__ . COLON . __LINE__) . COLON . sprintf(ERROR_UT_STRING_MISMATCH, $expectedResponse, $gotResponse));
}
/**
* testNegativeNIFQuery() -- unit test method
*
* this is a negative unit test - we coded this to fail. We want to submit a query with a predicate that
* contains a non-indexed field (NIF). One of the more-important features of Namaste is to evaluate and
* qualify query requests.
*
* Namaste does not allow query predicates with non-indexed fields and should reject these requests with a
* STATE_INDEX_ERROR state return.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 10-11-17 mks CORE:584: original coding, ported for PDO from mongo test
*
*/
public function testNegativeNIFQuery()
{
// legit query -- all values are = 1, but the field is not indexed so query should be rejected
$query = [ CM_TST_FIELD_TEST_NIF => [ OPERAND_NULL => [ OPERATOR_EQ => [ 42 ] ] ] ];
$request = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [STRING_QUERY_DATA => $query ],
BROKER_META_DATA => static::$meta
];
// build the request payload and submit the request to the read broker
$payload = gzcompress(json_encode($request));
$response = $this->readBrokerClient->call($payload);
$response = json_decode(gzuncompress($response), true);
// validate the response payload
$this->assertFalse($response[PAYLOAD_STATUS], (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_FALSE . PAYLOAD_STATUS);
$this->assertEquals(STATE_INDEX_ERROR , $response[PAYLOAD_STATE], (__FILE__ . COLON . __LINE__) . COLON . sprintf(ERROR_UT_FIELD_VALUE, PAYLOAD_STATE));
}
/**
* testFetchAll() -- unit test method
*
* this test is going to launch a null-query test. For this test to be successfully evaluated, you must have more
* records in the database than the queryRecordLimit set in the XML configuration. (currently: 100)
*
* we're launching a "get all the records" query without a limit clause in an attempt at fetching all the records
* in a collection. This is a very bad thing if your collection has a hundred-million rows, or more, of data.
*
* the namaste xml file limits the number of records returned in any given fetch query. When we submit a null
* query, we're not including the limit-value in the meta payload -- this should tell the framework to fetch all
* the collection's records.
*
* the framework should self-impose the record limit and that limit should be the value configured in the xml.
* we're going to test for that value as the number of records returned.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 10-11-17 mks CORE:584: original coding, ported for PDO from mongo test
*
*/
public function testFetchAll()
{
$recordLimit = gasConfig::$settings[CONFIG_DATABASE][CONFIG_DATABASE_QUERY_RECORD_LIMIT];
if (isset(static::$meta[META_LIMIT])) unset(static::$meta[META_LIMIT]);
if (isset(static::$meta[META_SKIP])) unset(static::$meta[META_SKIP]);
$request = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [STRING_QUERY_DATA => null ],
BROKER_META_DATA => static::$meta
];
// build the request payload and submit the request to the read broker
$payload = gzcompress(json_encode($request));
$response = $this->readBrokerClient->call($payload);
$response = json_decode(gzuncompress($response), true);
// validate that the return payload is an array
$this->assertTrue(is_array($response), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_MISSING_ARRAY . 'broker response');
// validate that the payload returned was successful
$this->assertTrue($response[PAYLOAD_STATUS], (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_TRUE . PAYLOAD_STATUS);
// validate that we returned the current-configured max-number of records
$recsReturned = $response[PAYLOAD_RESULTS][STRING_QUERY_DATA][STRING_REC_COUNT_RET];
$msg = sprintf(ERROR_UT_INTEGER_MISMATCH, $recordLimit, $recsReturned, STRING_REC_COUNT_RET);
$this->assertLessThanOrEqual($recordLimit, $recsReturned, (__FILE__ . COLON . __LINE__) . COLON . $msg);
}
/**
* testSkipLimit() -- unit test method
*
* this method validates the skip-limit processing accuracy for the framework.
*
* First, we're going to generate a random number that's equal to 25% of the total record count, +/- 10.
* Next, exec a query that returns a list of 100 sorted guids, starting with the offset we just calculated
* Next, generate a random number between 0 and 99 (1-100)
* Next, save the sorted list of guids to an array
* Next, exec a query that pulls that record (starting offset + rand-number) from the db
* Last, compare the single returned value against the value in the list stored at the calculated offset
*
* I tried to limit the number of assertions in this test based on if the same assertions had been previously
* tested in preceding methods.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* ========
* 10-11-17 mks CORE:584: original coding, ported for PDO from mongo test
* 10-17-17 mks CORE:584: rewrote b/c we changed the payload on multiple returned records
*
*/
public function testSkipLimit()
{
$this->assertGreaterThan(0, static::$maxRecordCount, sprintf(ERROR_UT_FIELD_VALUE, 'maxRecordCount'));
// build a query: fetch all active records
// point is to build a query that fetches a significant number of records...
$query = [CM_TST_FIELD_TEST_STATUS => [ OPERAND_NULL => [ OPERATOR_EQ => [STATUS_ACTIVE]]]];
// build the sort and projection arrays so we can test these options:
$sort = [ CM_TST_TOKEN => STRING_SORT_ASC ]; // sort by data-created ascending
$projection = [ CM_TST_TOKEN ]; // return a list of record guids
// build the request
$request = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [
STRING_QUERY_DATA => $query,
STRING_SORT_DATA => $sort,
STRING_RETURN_DATA => $projection
],
BROKER_META_DATA => static::$meta
];
// launch the query and let's pull out the token list
$payload = gzcompress(json_encode($request));
$response = $this->readBrokerClient->call($payload);
$response = json_decode(gzuncompress($response), true);
// validate that the return payload is an array
$this->assertTrue(is_array($response), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_MISSING_ARRAY . 'broker response');
// validate that the payload returned was successful
$this->assertTrue($response[PAYLOAD_STATUS], (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_TRUE . PAYLOAD_STATUS);
$this->assertNotEquals(STATE_NOT_FOUND, $response[PAYLOAD_STATE], basename(__METHOD__) . AT . __LINE__ . COLON . ERROR_UT_NOT_FOUND);
// save a copy of the sorted record list - this because our validation authority
$cacheGUID = $response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS][0];
$this->assertTrue(validateGUID(str_replace(gasConfig::$settings[CONFIG_ID][CONFIG_ID_ENV] . UDASH, '', $cacheGUID)), (__FILE__ . COLON . __LINE__) . ERROR_UT_CACHE_FETCH_FAIL);
$recordList = json_decode(gzuncompress(gasCache::get($cacheGUID)), true);
if (array_key_exists(STRING_CHECKSUM, $recordList)) unset($recordList[STRING_CHECKSUM]);
$this->assertTrue(count($recordList) <= static::$maxRecordCount, (__FILE__ . COLON . __LINE__) . COLON . sprintf(ERROR_DATA_ARRAY_COUNT_EXCESSIVE, count($recordList), static::$maxRecordCount));
// now - generate a new query to extract a random record within that range
$recCount = count($recordList);
$randomRecord = intval(mt_rand($recCount/4, $recCount));
static::$meta[META_SKIP] = $randomRecord;
static::$meta[META_LIMIT] = 1; // and retrieve only that record
// build the request
$request = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [
STRING_QUERY_DATA => $query,
STRING_SORT_DATA => $sort,
STRING_RETURN_DATA => $projection
],
BROKER_META_DATA => static::$meta
];
// submit the request and validate the payload return
$payload = gzcompress(json_encode($request));
$response = $this->readBrokerClient->call($payload);
$response = json_decode(gzuncompress($response), true);
// validate that the return payload is an array
$this->assertTrue(is_array($response), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_MISSING_ARRAY . 'broker response');
// validate that the payload returned was successful
$this->assertTrue($response[PAYLOAD_STATUS], (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_TRUE . PAYLOAD_STATUS);
$newRecord = $response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS][0];
$newRecord = json_decode(gzuncompress(gasCache::get($newRecord)), true);
$newRecordGuid = $newRecord[0][STRING_KEY];
$oldRecGuid = $recordList[$randomRecord][STRING_KEY];
$this->assertNotFalse(stristr($oldRecGuid, $newRecordGuid), (__FILE__ . COLON . __LINE__) . COLON . sprintf(ERROR_UT_VALS_NOT_EQUAL, $newRecordGuid, $oldRecGuid));
}
/**
* testNonCachedFetch() -- public unit test method
*
* The purpose of this unit test is to publish a fetch event request using the META_DONUT_FILTER flag in the meta
* data payload. We're submitting the request and limiting the fetch to be a single record.
*
* We're injecting the META_DONUT_FILTER as part of the meta-data payload to force the request to return the
* record containing the actual schema.
*
* The validation comes when we fetch the token from the record payload - each record is required to have one - and
* the act of isolating that record involves querying by the class extension: implicit proof that we fetched
* the pure version of the record.
*
*
* @author mike@givingassistant.org
* @version 1.0
*
*
* HISTORY:
* ========
* 05-23-19 mks DB-40: unit-tests for non-cached data classes: original coding
*
*/
public function testNonCachedFetch()
{
$query = null;
$metaCopy = static::$meta;
// limit the return data count to 1 record (we'll test for this...)
$metaCopy[META_LIMIT] = 1;
$metaCopy[META_EVENT_GUID] = guid();
$metaCopy[META_SYSTEM_NOTES] = basename(__METHOD__) . AT . __LINE__;
$metaCopy[META_DONUT_FILTER] = 1; // don't filter the return payload
// set up the broker request
$request = [
BROKER_REQUEST => BROKER_REQUEST_FETCH,
BROKER_DATA => [STRING_QUERY_DATA => $query ],
BROKER_META_DATA => $metaCopy
];
$payload = gzcompress(json_encode($request));
$response = $this->readBrokerClient->call($payload);
$response = json_decode(gzuncompress($response), true);
// validate that the return payload is an array
$this->assertTrue(is_array($response), (__FILE__ . COLON . __LINE__) . COLON . ERROR_DATA_MISSING_ARRAY . 'broker response');
// validate that the payload returned was successful
$this->assertTrue($response[PAYLOAD_STATUS], (__FILE__ . COLON . __LINE__) . COLON . ERROR_UT_EXPECTING_TRUE . PAYLOAD_STATUS);
$tok = $response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS][0][DB_TOKEN . TABLE_EXT_TEST];
$this->assertTrue(validateGUID($tok), basename(__METHOD__) . AT . __LINE__ . COLON . ERROR_INVALID_GUID . $tok);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff