From 86e30ffbae4f551caceb3c554c2ffa4a4b39f44a Mon Sep 17 00:00:00 2001 From: liugang Date: Wed, 14 Jan 2026 20:15:31 +0800 Subject: [PATCH 1/2] * [refac] Support calling static methods by baseTest::invokeArgs() method. --- test/lib/test.class.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/lib/test.class.php b/test/lib/test.class.php index a6e754169c..bc2e9e0532 100644 --- a/test/lib/test.class.php +++ b/test/lib/test.class.php @@ -203,6 +203,7 @@ class baseTest $method = $reflection->getMethod($methodName); if(!$method->isPublic()) $method->setAccessible(true); - return $method->invokeArgs($instance, $args); + $object = $method->isStatic() ? null : $instance; + return $method->invokeArgs($object, $args); } } From faf0fcbe600ff4d7fa733048ff9b54e7e24e7470 Mon Sep 17 00:00:00 2001 From: liugang Date: Wed, 14 Jan 2026 20:16:34 +0800 Subject: [PATCH 2/2] * [refac] Refactor test lib classes. --- module/action/test/lib/model.class.php | 401 +-- module/action/test/lib/tao.class.php | 389 +++ module/ai/test/lib/model.class.php | 143 +- module/aiapp/test/lib/model.class.php | 34 +- module/api/test/lib/model.class.php | 2 - module/api/test/lib/zen.class.php | 793 +----- module/backup/test/lib/model.class.php | 280 +- module/bi/test/lib/model.class.php | 2346 +---------------- module/bi/test/lib/tao.class.php | 3194 +---------------------- module/bi/test/model/gettablefields.php | 29 - 10 files changed, 520 insertions(+), 7091 deletions(-) delete mode 100755 module/bi/test/model/gettablefields.php diff --git a/module/action/test/lib/model.class.php b/module/action/test/lib/model.class.php index fad5612491..e47aa002e8 100644 --- a/module/action/test/lib/model.class.php +++ b/module/action/test/lib/model.class.php @@ -989,25 +989,7 @@ class actionModelTest extends baseTest */ public function getObjectTypeTeamParamsTest($action) { - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('getObjectTypeTeamParams'); - $method->setAccessible(true); - - $result = $method->invoke($this->instance, $action); - if(dao::isError()) return dao::getError(); - return $result; - } - - /** - * Test processAttribute method. - * - * @param string $type - * @access public - * @return string - */ - public function processAttributeTest(string $type): string - { - $result = $this->objectTao->processAttribute($type); + $result = $this->invokeArgs('getObjectTypeTeamParams', [$action]); if(dao::isError()) return dao::getError(); return $result; } @@ -1022,386 +1004,7 @@ class actionModelTest extends baseTest */ public function checkActionCanUndeleteTest($action, $object) { - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('checkActionCanUndelete'); - $method->setAccessible(true); - - $result = $method->invoke($this->instance, $action, $object); - if(dao::isError()) return dao::getError(); - return $result; - } - - /** - * Test getLinkedExtra method. - * - * @param object $action - * @param string $type - * @access public - * @return bool - */ - public function getLinkedExtraTest(object $action, string $type): bool - { - $result = $this->objectTao->getLinkedExtra($action, $type); - if(dao::isError()) return dao::getError(); - return $result; - } - - /** - * Test processActionExtra method. - * - * @param string $table - * @param int $extraID - * @param string $fields - * @param string $type - * @param string $method - * @param bool $onlyBody - * @param bool $addLink - * @access public - * @return string - */ - public function processActionExtraTest(string $table, int $extraID, string $fields, string $type, string $method = 'view', bool $onlyBody = false, bool $addLink = true): string - { - // 创建测试用的action对象 - $action = new stdClass(); - $action->extra = $extraID; - $action->objectType = 'bug'; - $action->action = 'converttotask'; - $action->project = 1; - - $originalExtra = $action->extra; // 备份原始extra值 - - // 模拟onlyBody场景 - if($onlyBody) - { - $originalIsonlybody = $this->instance->config->requestType ?? 'GET'; - $_GET['onlybody'] = 'yes'; - } - - $this->objectTao->processActionExtra($table, $action, $fields, $type, $method, $onlyBody, $addLink); - if(dao::isError()) return dao::getError(); - - if($onlyBody) unset($_GET['onlybody']); // 恢复onlyBody状态 - - // 分析结果 - 优先检查特殊场景 - if($action->extra == $originalExtra) return 'no_change'; - if($onlyBody && strpos($action->extra, 'extra, '#') !== false && strpos($action->extra, 'objectType == 'bug' && $type == 'task' && strpos($action->extra, 'data-app=') !== false) return 'bug_to_task'; - if(strpos($action->extra, 'objectID = $storyID; - $action->extra = ''; - - $result = $this->objectTao->processStoryGradeActionExtra($action); - if(dao::isError()) return dao::getError(); - return $result; - } - - /** - * Test processParamString method. - * - * @param object $action - * @param string $type - * @access public - * @return string - */ - public function processParamStringTest(object $action, string $type): string - { - $result = $this->objectTao->processParamString($action, $type); - if(dao::isError()) return dao::getError(); - return $result; - } - - /** - * Test processCreateChildrenActionExtra method. - * - * @param string $taskIds - * @access public - * @return object - */ - public function processCreateChildrenActionExtraTest(string $taskIds): object - { - // 创建模拟的action对象 - $action = new stdClass(); - $action->extra = $taskIds; - - $this->objectTao->processCreateChildrenActionExtra($action); - if(dao::isError()) return dao::getError(); - return $action; - } - - /** - * Test processCreateRequirementsActionExtra method. - * - * @param string $storyIds - * @access public - * @return object - */ - public function processCreateRequirementsActionExtraTest(string $storyIds): object - { - // 创建模拟的action对象 - $action = new stdClass(); - $action->extra = $storyIds; - - $this->objectTao->processCreateRequirementsActionExtra($action); - if(dao::isError()) return dao::getError(); - return $action; - } - - /** - * Test processAppendLinkByExtra method. - * - * @param string $extra - * @param string $objectType - * @access public - * @return object - */ - public function processAppendLinkByExtraTest(string $extra, string $objectType = 'task'): object - { - $action = new stdClass(); - $action->extra = $extra; - $action->objectType = $objectType; - - $this->objectTao->processAppendLinkByExtra($action); - if(dao::isError()) return dao::getError(); - return $action; - } - - /** - * Test processLinkStoryAndBugActionExtra method. - * - * @param string $extra - * @param string $module - * @param string $method - * @access public - * @return object - */ - public function processLinkStoryAndBugActionExtraTest(string $extra, string $module, string $method): object - { - $action = new stdClass(); - $action->extra = $extra; - - $this->objectTao->processLinkStoryAndBugActionExtra($action, $module, $method); - return $action; - } - - /** - * Test processToStoryActionExtra method. - * - * @param object $action - * @access public - * @return object - */ - public function processToStoryActionExtraTest(object $action): object - { - $this->objectTao->processToStoryActionExtra($action); - if(dao::isError()) return dao::getError(); - return $action; - } - - /** - * Test getActionTable method. - * - * @param string $period - * @access public - * @return string - */ - public function getActionTableTest(string $period): string - { - $result = $this->objectTao->getActionTable($period); - if(dao::isError()) return dao::getError(); - return $result; - } - - /** - * Test addObjectNameForAction method. - * - * @param string $objectType - * @param int $objectID - * @param array $objectNames - * @param string $actionType - * @param string $extra - * @access public - * @return object - */ - public function addObjectNameForActionTest(string $objectType, int $objectID, array $objectNames, string $actionType = '', string $extra = ''): object - { - // 创建测试用的action对象 - $action = new stdClass(); - $action->objectType = $objectType; - $action->objectID = $objectID; - $action->action = $actionType; - $action->extra = $extra; - $action->objectName = ''; - - $this->objectTao->addObjectNameForAction($action, $objectNames, $objectType); - if(dao::isError()) return dao::getError(); - return $action; - } - - /** - * Test processMaxDocObjectLink method. - * - * @param object $action - * @param string $moduleName - * @param string $methodName - * @param string $vars - * @access public - * @return object - */ - public function processMaxDocObjectLinkTest(object $action, string $moduleName, string $methodName, string $vars): object - { - $this->objectTao->processMaxDocObjectLink($action, $moduleName, $methodName, $vars); - if(dao::isError()) return dao::getError(); - return $action; - } - - /** - * Test getDocLibLinkParameters method. - * - * @param object $action - * @access public - * @return array|bool - */ - public function getDocLibLinkParametersTest(object $action) - { - $result = $this->objectTao->getDocLibLinkParameters($action); - if(dao::isError()) return dao::getError(); - return $result; - } - - /** - * Test getDoclibTypeParams method. - * - * @param object $action - * @access public - * @return array - */ - public function getDoclibTypeParamsTest(object $action): array - { - $result = $this->objectTao->getDoclibTypeParams($action); - if(dao::isError()) return dao::getError(); - return $result; - } - - /** - * Test getObjectLinkParams method. - * - * @param object $action - * @param string $vars - * @access public - * @return string - */ - public function getObjectLinkParamsTest(object $action, string $vars): string - { - $result = $this->objectTao->getObjectLinkParams($action, $vars); - if(dao::isError()) return dao::getError(); - return $result; - } - - /** - * Test getReleaseRelated method. - * - * @param string $objectType - * @param int $objectID - * @access public - * @return array - */ - public function getReleaseRelated(string $objectType, int $objectID): array - { - $result = $this->objectTao->getReleaseRelated($objectType, $objectID); - if(dao::isError()) return dao::getError(); - return $result; - } - - /** - * Test getReviewRelated method. - * - * @param string $objectType - * @param int $objectID - * @access public - * @return array - */ - public function getReviewRelatedTest(string $objectType, int $objectID): array - { - $result = $this->objectTao->getReviewRelated($objectType, $objectID); - if(dao::isError()) return dao::getError(); - return $result; - } - - /** - * Test getNeedRelatedFields method. - * - * @param string $objectType - * @param int $objectID - * @param string $actionType - * @param string $extra - * @access public - * @return array - */ - public function getNeedRelatedFieldsTest(string $objectType, int $objectID, string $actionType = '', string $extra = ''): array - { - $result = $this->objectTao->getNeedRelatedFields($objectType, $objectID, $actionType, $extra); - if(dao::isError()) return dao::getError(); - return $result; - } - - /** - * Test getGenerateRelated method. - * - * @param string $objectType - * @param int $objectID - * @access public - * @return array - */ - public function getGenerateRelatedTest(string $objectType, int $objectID): array - { - $result = $this->objectTao->getGenerateRelated($objectType, $objectID); - if(dao::isError()) return dao::getError(); - return $result; - } - - /** - * Test getTaskRelated method. - * - * @param string $objectType - * @param int $objectID - * @access public - * @return array - */ - public function getTaskRelated(string $objectType, int $objectID): array - { - $result = $this->objectTao->getTaskRelated($objectType, $objectID); - if(dao::isError()) return dao::getError(); - return $result; - } - - /** - * 根据类型和ID获取操作记录列表。 - * Get action list by type and ID. - * - * @param string $objectType - * @param int|array $objectID - * @param array $modules - * @access public - * @return array - */ - public function getActionListByTypeAndIDTest(string $objectType, int|array $objectID, array $modules): array - { - $result = $this->objectTao->getActionListByTypeAndID($objectType, $objectID, $modules); + $result = $this->invokeArgs('checkActionCanUndelete', [$action, $object]); if(dao::isError()) return dao::getError(); return $result; } diff --git a/module/action/test/lib/tao.class.php b/module/action/test/lib/tao.class.php index 3f4cf11731..0ba3e8851e 100644 --- a/module/action/test/lib/tao.class.php +++ b/module/action/test/lib/tao.class.php @@ -62,4 +62,393 @@ class actionTaoTest extends baseTest if(dao::isError()) return dao::getError(); return $action; } + + /** + * Test processAttribute method. + * + * @param string $type + * @access public + * @return string + */ + public function processAttributeTest(string $type): string + { + $result = $this->instance->processAttribute($type); + if(dao::isError()) return dao::getError(); + return $result; + } + + /** + * Test getLinkedExtra method. + * + * @param object $action + * @param string $type + * @access public + * @return bool + */ + public function getLinkedExtraTest(object $action, string $type): bool + { + $result = $this->instance->getLinkedExtra($action, $type); + if(dao::isError()) return dao::getError(); + return $result; + } + + /** + * Test processActionExtra method. + * + * @param string $table + * @param int $extraID + * @param string $fields + * @param string $type + * @param string $method + * @param bool $onlyBody + * @param bool $addLink + * @access public + * @return string + */ + public function processActionExtraTest(string $table, int $extraID, string $fields, string $type, string $method = 'view', bool $onlyBody = false, bool $addLink = true): string + { + // 创建测试用的action对象 + $action = new stdClass(); + $action->extra = $extraID; + $action->objectType = 'bug'; + $action->action = 'converttotask'; + $action->project = 1; + + $originalExtra = $action->extra; // 备份原始extra值 + + // 模拟onlyBody场景 + if($onlyBody) + { + $originalIsonlybody = $this->instance->config->requestType ?? 'GET'; + $_GET['onlybody'] = 'yes'; + } + + $this->instance->processActionExtra($table, $action, $fields, $type, $method, $onlyBody, $addLink); + if(dao::isError()) return dao::getError(); + + if($onlyBody) unset($_GET['onlybody']); // 恢复onlyBody状态 + + // 分析结果 - 优先检查特殊场景 + if($action->extra == $originalExtra) return 'no_change'; + if($onlyBody && strpos($action->extra, 'extra, '#') !== false && strpos($action->extra, 'objectType == 'bug' && $type == 'task' && strpos($action->extra, 'data-app=') !== false) return 'bug_to_task'; + if(strpos($action->extra, 'objectID = $storyID; + $action->extra = ''; + + $result = $this->instance->processStoryGradeActionExtra($action); + if(dao::isError()) return dao::getError(); + return $result; + } + + /** + * Test processParamString method. + * + * @param object $action + * @param string $type + * @access public + * @return string + */ + public function processParamStringTest(object $action, string $type): string + { + $result = $this->instance->processParamString($action, $type); + if(dao::isError()) return dao::getError(); + return $result; + } + + /** + * Test processCreateChildrenActionExtra method. + * + * @param string $taskIds + * @access public + * @return object + */ + public function processCreateChildrenActionExtraTest(string $taskIds): object + { + // 创建模拟的action对象 + $action = new stdClass(); + $action->extra = $taskIds; + + $this->instance->processCreateChildrenActionExtra($action); + if(dao::isError()) return dao::getError(); + return $action; + } + + /** + * Test processCreateRequirementsActionExtra method. + * + * @param string $storyIds + * @access public + * @return object + */ + public function processCreateRequirementsActionExtraTest(string $storyIds): object + { + // 创建模拟的action对象 + $action = new stdClass(); + $action->extra = $storyIds; + + $this->instance->processCreateRequirementsActionExtra($action); + if(dao::isError()) return dao::getError(); + return $action; + } + + /** + * Test processAppendLinkByExtra method. + * + * @param string $extra + * @param string $objectType + * @access public + * @return object + */ + public function processAppendLinkByExtraTest(string $extra, string $objectType = 'task'): object + { + $action = new stdClass(); + $action->extra = $extra; + $action->objectType = $objectType; + + $this->instance->processAppendLinkByExtra($action); + if(dao::isError()) return dao::getError(); + return $action; + } + + /** + * Test processLinkStoryAndBugActionExtra method. + * + * @param string $extra + * @param string $module + * @param string $method + * @access public + * @return object + */ + public function processLinkStoryAndBugActionExtraTest(string $extra, string $module, string $method): object + { + $action = new stdClass(); + $action->extra = $extra; + + $this->instance->processLinkStoryAndBugActionExtra($action, $module, $method); + return $action; + } + + /** + * Test processToStoryActionExtra method. + * + * @param object $action + * @access public + * @return object + */ + public function processToStoryActionExtraTest(object $action): object + { + $this->instance->processToStoryActionExtra($action); + if(dao::isError()) return dao::getError(); + return $action; + } + + /** + * Test getActionTable method. + * + * @param string $period + * @access public + * @return string + */ + public function getActionTableTest(string $period): string + { + $result = $this->instance->getActionTable($period); + if(dao::isError()) return dao::getError(); + return $result; + } + + /** + * Test addObjectNameForAction method. + * + * @param string $objectType + * @param int $objectID + * @param array $objectNames + * @param string $actionType + * @param string $extra + * @access public + * @return object + */ + public function addObjectNameForActionTest(string $objectType, int $objectID, array $objectNames, string $actionType = '', string $extra = ''): object + { + // 创建测试用的action对象 + $action = new stdClass(); + $action->objectType = $objectType; + $action->objectID = $objectID; + $action->action = $actionType; + $action->extra = $extra; + $action->objectName = ''; + + $this->instance->addObjectNameForAction($action, $objectNames, $objectType); + if(dao::isError()) return dao::getError(); + return $action; + } + + /** + * Test processMaxDocObjectLink method. + * + * @param object $action + * @param string $moduleName + * @param string $methodName + * @param string $vars + * @access public + * @return object + */ + public function processMaxDocObjectLinkTest(object $action, string $moduleName, string $methodName, string $vars): object + { + $this->instance->processMaxDocObjectLink($action, $moduleName, $methodName, $vars); + if(dao::isError()) return dao::getError(); + return $action; + } + + /** + * Test getDocLibLinkParameters method. + * + * @param object $action + * @access public + * @return array|bool + */ + public function getDocLibLinkParametersTest(object $action) + { + $result = $this->instance->getDocLibLinkParameters($action); + if(dao::isError()) return dao::getError(); + return $result; + } + + /** + * Test getDoclibTypeParams method. + * + * @param object $action + * @access public + * @return array + */ + public function getDoclibTypeParamsTest(object $action): array + { + $result = $this->instance->getDoclibTypeParams($action); + if(dao::isError()) return dao::getError(); + return $result; + } + + /** + * Test getObjectLinkParams method. + * + * @param object $action + * @param string $vars + * @access public + * @return string + */ + public function getObjectLinkParamsTest(object $action, string $vars): string + { + $result = $this->instance->getObjectLinkParams($action, $vars); + if(dao::isError()) return dao::getError(); + return $result; + } + + /** + * Test getReleaseRelated method. + * + * @param string $objectType + * @param int $objectID + * @access public + * @return array + */ + public function getReleaseRelated(string $objectType, int $objectID): array + { + $result = $this->instance->getReleaseRelated($objectType, $objectID); + if(dao::isError()) return dao::getError(); + return $result; + } + + /** + * Test getReviewRelated method. + * + * @param string $objectType + * @param int $objectID + * @access public + * @return array + */ + public function getReviewRelatedTest(string $objectType, int $objectID): array + { + $result = $this->instance->getReviewRelated($objectType, $objectID); + if(dao::isError()) return dao::getError(); + return $result; + } + + /** + * Test getNeedRelatedFields method. + * + * @param string $objectType + * @param int $objectID + * @param string $actionType + * @param string $extra + * @access public + * @return array + */ + public function getNeedRelatedFieldsTest(string $objectType, int $objectID, string $actionType = '', string $extra = ''): array + { + $result = $this->instance->getNeedRelatedFields($objectType, $objectID, $actionType, $extra); + if(dao::isError()) return dao::getError(); + return $result; + } + + /** + * Test getGenerateRelated method. + * + * @param string $objectType + * @param int $objectID + * @access public + * @return array + */ + public function getGenerateRelatedTest(string $objectType, int $objectID): array + { + $result = $this->instance->getGenerateRelated($objectType, $objectID); + if(dao::isError()) return dao::getError(); + return $result; + } + + /** + * Test getTaskRelated method. + * + * @param string $objectType + * @param int $objectID + * @access public + * @return array + */ + public function getTaskRelated(string $objectType, int $objectID): array + { + $result = $this->instance->getTaskRelated($objectType, $objectID); + if(dao::isError()) return dao::getError(); + return $result; + } + + /** + * 根据类型和ID获取操作记录列表。 + * Get action list by type and ID. + * + * @param string $objectType + * @param int|array $objectID + * @param array $modules + * @access public + * @return array + */ + public function getActionListByTypeAndIDTest(string $objectType, int|array $objectID, array $modules): array + { + $result = $this->instance->getActionListByTypeAndID($objectType, $objectID, $modules); + if(dao::isError()) return dao::getError(); + return $result; + } } diff --git a/module/ai/test/lib/model.class.php b/module/ai/test/lib/model.class.php index 056950c2ee..e0b3d19c24 100644 --- a/module/ai/test/lib/model.class.php +++ b/module/ai/test/lib/model.class.php @@ -182,12 +182,8 @@ class aiModelTest extends baseTest */ public function getDefaultLanguageModelTest() { - // 使用反射来测试私有方法 - $method = new ReflectionMethod($this->instance, 'getDefaultLanguageModel'); - $method->setAccessible(true); - $result = $method->invoke($this->instance); + $result = $this->invokeArgs('getDefaultLanguageModel'); if(dao::isError()) return dao::getError(); - return $result; } @@ -200,13 +196,8 @@ class aiModelTest extends baseTest */ public function serializeModelTest($model = null) { - /* Using reflection to call private method */ - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('serializeModel'); - $method->setAccessible(true); - $result = $method->invoke($this->instance, $model); + $result = $this->invokeArgs('serializeModel', [$model]); if(dao::isError()) return dao::getError(); - return $result; } @@ -221,7 +212,6 @@ class aiModelTest extends baseTest { $result = $this->instance->unserializeModel($model); if(dao::isError()) return dao::getError(); - return $result; } @@ -236,7 +226,6 @@ class aiModelTest extends baseTest { $result = $this->instance->createModel($model); if(dao::isError()) return dao::getError(); - return $result; } @@ -405,13 +394,8 @@ class aiModelTest extends baseTest */ public function getProxyTypeTest($proxyType = null) { - /* Using reflection to call private static method */ - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('getProxyType'); - $method->setAccessible(true); - $result = $method->invoke(null, $proxyType); + $result = $this->invokeArgs('getProxyType', [$proxyType]); if(dao::isError()) return dao::getError(); - return $result; } @@ -424,13 +408,8 @@ class aiModelTest extends baseTest */ public function camelCaseToSnakeCaseTest($str = null) { - /* Using reflection to call private static method */ - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('camelCaseToSnakeCase'); - $method->setAccessible(true); - $result = $method->invoke(null, $str); + $result = $this->invokeArgs('camelCaseToSnakeCase', [$str]); if(dao::isError()) return dao::getError(); - return $result; } @@ -443,13 +422,8 @@ class aiModelTest extends baseTest */ public function standardizeParamsTest($data = null) { - /* Using reflection to call private static method */ - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('standardizeParams'); - $method->setAccessible(true); - $result = $method->invoke(null, $data); + $result = $this->invokeArgs(i'standardizeParams', [$data]); if(dao::isError()) return dao::getError(); - return $result; } @@ -463,13 +437,8 @@ class aiModelTest extends baseTest */ public function assembleRequestDataTest($type = null, $data = null) { - /* Using reflection to call private method */ - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('assembleRequestData'); - $method->setAccessible(true); - $result = $method->invoke($this->instance, $type, $data); + $result = $this->invokeArgs('assembleRequestData', [$type, $data]); if(dao::isError()) return dao::getError(); - return $result; } @@ -482,13 +451,8 @@ class aiModelTest extends baseTest */ public function decodeResponseTest($response = null) { - /* Using reflection to call private method */ - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('decodeResponse'); - $method->setAccessible(true); - $result = $method->invoke($this->instance, $response); + $result = $this->invokeArgs('decodeResponse', [$response]); if(dao::isError()) return dao::getError(); - return $result; } @@ -501,13 +465,8 @@ class aiModelTest extends baseTest */ public function parseTextResponseTest($response = null) { - /* Using reflection to call private method */ - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('parseTextResponse'); - $method->setAccessible(true); - $result = $method->invoke($this->instance, $response); + $result = $this->invokeArgs('parseTextResponse', [$response]); if(dao::isError()) return dao::getError(); - return $result; } @@ -520,13 +479,8 @@ class aiModelTest extends baseTest */ public function parseChatResponseTest($response = null) { - /* Using reflection to call private method */ - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('parseChatResponse'); - $method->setAccessible(true); - $result = $method->invoke($this->instance, $response); + $result = $this->invokeArgs('parseChatResponse', [$response]); if(dao::isError()) return dao::getError(); - return $result; } @@ -539,13 +493,8 @@ class aiModelTest extends baseTest */ public function parseFunctionCallResponseTest($response = null) { - /* Using reflection to call private method */ - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('parseFunctionCallResponse'); - $method->setAccessible(true); - $result = $method->invoke($this->instance, $response); + $result = $this->invokeArgs('parseFunctionCallResponse', [$response]); if(dao::isError()) return dao::getError(); - return $result; } @@ -656,7 +605,6 @@ class aiModelTest extends baseTest { $result = $this->instance->converse($model, $messages, $options); if(dao::isError()) return dao::getError(); - return $result; } @@ -846,7 +794,6 @@ class aiModelTest extends baseTest { $result = $this->instance->countLatestMiniPrograms(); if(dao::isError()) return dao::getError(); - return $result; } @@ -863,7 +810,6 @@ class aiModelTest extends baseTest { $result = $this->instance->saveMiniProgramMessage($appID, $type, $content); if(dao::isError()) return dao::getError(); - return $result; } @@ -880,7 +826,6 @@ class aiModelTest extends baseTest { $result = $this->instance->deleteHistoryMessagesByID($appID, $userID, $messageIDs); if(dao::isError()) return dao::getError(); - return $result; } @@ -896,7 +841,6 @@ class aiModelTest extends baseTest { $result = $this->instance->getHistoryMessages($appID, $limit); if(dao::isError()) return dao::getError(); - return $result; } @@ -1057,7 +1001,6 @@ class aiModelTest extends baseTest { $result = $this->instance->getMiniProgramByID($id); if(dao::isError()) return dao::getError(); - return $result; } @@ -1071,7 +1014,6 @@ class aiModelTest extends baseTest { $result = $this->instance->getCustomCategories(); if(dao::isError()) return dao::getError(); - return $result; } @@ -1085,7 +1027,6 @@ class aiModelTest extends baseTest { $result = $this->instance->getUsedCustomCategories(); if(dao::isError()) return dao::getError(); - return $result; } @@ -1099,7 +1040,6 @@ class aiModelTest extends baseTest { $result = $this->instance->getPublishedCustomCategories(); if(dao::isError()) return dao::getError(); - return $result; } @@ -1115,7 +1055,6 @@ class aiModelTest extends baseTest $_POST = $postData; $result = $this->instance->checkDuplicatedCategory(); if(dao::isError()) return dao::getError(); - return $result; } @@ -1133,7 +1072,6 @@ class aiModelTest extends baseTest { $result = $this->instance->getMiniPrograms($category, $status, $order, $pager); if(dao::isError()) return dao::getError(); - return $result; } @@ -1148,7 +1086,6 @@ class aiModelTest extends baseTest { $result = $this->instance->getMiniProgramFields($appID); if(dao::isError()) return dao::getError(); - return $result; } @@ -1203,7 +1140,6 @@ class aiModelTest extends baseTest { $result = $this->instance->publishMiniProgram($appID, $published); if(dao::isError()) return dao::getError(); - return $result; } @@ -1220,7 +1156,6 @@ class aiModelTest extends baseTest { $result = $this->instance->collectMiniProgram($userID, $appID, $delete); if(dao::isError()) return dao::getError(); - return $result; } @@ -1235,7 +1170,6 @@ class aiModelTest extends baseTest { $result = $this->instance->canPublishMiniProgram($program); if(dao::isError()) return dao::getError(); - return $result; } @@ -1250,7 +1184,6 @@ class aiModelTest extends baseTest { $result = $this->instance->createMiniProgram($data); if(dao::isError()) return dao::getError(); - return $result; } @@ -1330,7 +1263,6 @@ class aiModelTest extends baseTest { $result = $this->instance->checkDuplicatedAppName($name, $appID); if(dao::isError()) return dao::getError(); - return $result ? '1' : '0'; } @@ -1345,7 +1277,6 @@ class aiModelTest extends baseTest { $result = $this->instance->getUniqueAppName($name); if(dao::isError()) return dao::getError(); - return $result; } @@ -1362,7 +1293,6 @@ class aiModelTest extends baseTest $_POST = $postData; $result = $this->instance->verifyRequiredFields($requiredFields); if(dao::isError()) return dao::getError(); - return $result; } @@ -1380,7 +1310,6 @@ class aiModelTest extends baseTest { $result = $this->instance->getPrompts($module, $status, $order, $pager); if(dao::isError()) return dao::getError(); - return $result; } @@ -1395,7 +1324,6 @@ class aiModelTest extends baseTest { $result = $this->instance->getPromptById($id); if(dao::isError()) return dao::getError(); - return $result; } @@ -1410,7 +1338,6 @@ class aiModelTest extends baseTest { $result = $this->instance->getPromptFields($promptID); if(dao::isError()) return dao::getError(); - return $result; } @@ -1425,7 +1352,6 @@ class aiModelTest extends baseTest { $result = $this->instance->createPrompt($prompt); if(dao::isError()) return dao::getError(); - return $result; } @@ -1442,12 +1368,11 @@ class aiModelTest extends baseTest $this->instance->savePromptFields($promptID, $data); if(dao::isError()) return dao::getError(); - $fields = $this->instance->dao->select('*') + $count = $this->instance->dao->select('COUNT(1) AS count') ->from(TABLE_AI_PROMPTFIELD) ->where('appID')->eq($promptID) - ->fetchAll(); - - return count($fields); + ->fetch('count'); + return $count; } /** @@ -1462,7 +1387,6 @@ class aiModelTest extends baseTest { $result = $this->instance->updatePrompt($prompt, $originalPrompt); if(dao::isError()) return dao::getError(); - return $result; } @@ -1477,7 +1401,6 @@ class aiModelTest extends baseTest { $result = $this->instance->deletePrompt($id); if(dao::isError()) return dao::getError(); - return $result; } @@ -1493,7 +1416,6 @@ class aiModelTest extends baseTest { $result = $this->instance->togglePromptStatus($prompt, $status); if(dao::isError()) return dao::getError(); - return $result; } @@ -1691,13 +1613,8 @@ class aiModelTest extends baseTest */ public function isAssocTest($array = null) { - /* Using reflection to call private static method */ - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('isAssoc'); - $method->setAccessible(true); - $result = $method->invoke(null, $array); + $result = $this->invokeArgs('isAssoc', [$array]); if(dao::isError()) return dao::getError(); - return $result; } @@ -1800,13 +1717,8 @@ class aiModelTest extends baseTest */ public function autoPrependNewlineTest($text = '') { - $reflectionClass = new ReflectionClass('aiModel'); - $method = $reflectionClass->getMethod('autoPrependNewline'); - $method->setAccessible(true); - - $result = $method->invoke(null, $text); + $result = $this->invokeArgs('autoPrependNewline', [$text]); if(dao::isError()) return dao::getError(); - return $result; } @@ -1820,13 +1732,8 @@ class aiModelTest extends baseTest */ public function tryPunctuateTest($sentence = '', $newline = false) { - $reflectionClass = new ReflectionClass('aiModel'); - $method = $reflectionClass->getMethod('tryPunctuate'); - $method->setAccessible(true); - - $result = $method->invoke(null, $sentence, $newline); + $result = $this->invokeArgs('tryPunctuate', [$sentence, $newline]); if(dao::isError()) return dao::getError(); - return $result; } @@ -1842,7 +1749,6 @@ class aiModelTest extends baseTest { $result = aiModel::assemblePrompt($prompt, $dataPrompt); if(dao::isError()) return dao::getError(); - return $result; } @@ -1857,7 +1763,6 @@ class aiModelTest extends baseTest { $result = $this->instance->isExecutable($prompt); if(dao::isError()) return dao::getError(); - return $result; } @@ -2140,7 +2045,6 @@ class aiModelTest extends baseTest { $result = $this->instance->tryGetRelatedObjects($prompt, $object, $objectNames); if(dao::isError()) return dao::getError(); - return $result; } @@ -2155,7 +2059,6 @@ class aiModelTest extends baseTest { $result = $this->instance->getLastActiveStep($prompt); if(dao::isError()) return dao::getError(); - return $result; } @@ -2217,7 +2120,6 @@ class aiModelTest extends baseTest { $result = $this->instance->filterPromptsForExecution($prompts, $keepUnauthorized); if(dao::isError()) return dao::getError(); - return $result; } @@ -2233,7 +2135,6 @@ class aiModelTest extends baseTest { $this->instance->setInjectData($form, $data); if(dao::isError()) return dao::getError(); - return '0'; } @@ -2247,7 +2148,6 @@ class aiModelTest extends baseTest { $result = $this->instance->getRoleTemplates(); if(dao::isError()) return dao::getError(); - return $result; } @@ -2263,7 +2163,6 @@ class aiModelTest extends baseTest { $result = $this->instance->createRoleTemplate($role, $characterization); if(dao::isError()) return dao::getError(); - return $result; } @@ -2278,7 +2177,6 @@ class aiModelTest extends baseTest { $result = $this->instance->deleteRoleTemplate($id); if(dao::isError()) return dao::getError(); - return $result; } @@ -2295,7 +2193,6 @@ class aiModelTest extends baseTest { $result = $this->instance->updateRoleTemplate($id, $role, $characterization); if(dao::isError()) return dao::getError(); - return $result; } @@ -2311,7 +2208,6 @@ class aiModelTest extends baseTest { $result = $this->instance->getAssistants($pager, $orderBy); if(dao::isError()) return dao::getError(); - return $result; } @@ -2387,7 +2283,6 @@ class aiModelTest extends baseTest { $result = $this->instance->getAssistantById($assistantId); if(dao::isError()) return dao::getError(); - return $result; } @@ -2403,7 +2298,6 @@ class aiModelTest extends baseTest { $result = $this->instance->createAssistant($assistant, $publish); if(dao::isError()) return dao::getError(); - return $result; } @@ -2418,7 +2312,6 @@ class aiModelTest extends baseTest { $result = $this->instance->updateAssistant($assistant); if(dao::isError()) return dao::getError(); - return $result; } @@ -2434,7 +2327,6 @@ class aiModelTest extends baseTest { $result = $this->instance->toggleAssistant($assistantId, $enabled); if(dao::isError()) return dao::getError(); - return $result; } @@ -2450,7 +2342,6 @@ class aiModelTest extends baseTest { $result = $this->instance->checkAssistantDuplicate($assistantName, $modelId); if(dao::isError()) return dao::getError(); - return $result; } @@ -2467,7 +2358,6 @@ class aiModelTest extends baseTest $result = $this->instance->deleteAssistant($assistantId); if(dao::isError()) return dao::getError(); - return $result ? '1' : '0'; } @@ -2482,7 +2372,6 @@ class aiModelTest extends baseTest { $result = $this->instance->getTestPromptData($prompt); if(dao::isError()) return dao::getError(); - return !empty($result[1]) ? '1' : '0'; } diff --git a/module/aiapp/test/lib/model.class.php b/module/aiapp/test/lib/model.class.php index 611468bdc7..1b45601743 100644 --- a/module/aiapp/test/lib/model.class.php +++ b/module/aiapp/test/lib/model.class.php @@ -8,20 +8,6 @@ class aiappModelTest extends baseTest protected $moduleName = 'aiapp'; protected $className = 'model'; - /** - * Test __construct method. - * - * @access public - * @return mixed - */ - public function __constructTest() - { - $result = $this->instance; - if(dao::isError()) return dao::getError(); - - return $result; - } - /** * Test getLatestMiniPrograms method. * @@ -34,7 +20,6 @@ class aiappModelTest extends baseTest { $result = $this->instance->getLatestMiniPrograms($pager, $order); if(dao::isError()) return dao::getError(); - return $result; } @@ -46,12 +31,8 @@ class aiappModelTest extends baseTest */ public function countLatestMiniProgramsTest() { - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('countLatestMiniPrograms'); - $method->setAccessible(true); - $result = $method->invoke($this->instance); + $result = $this->invokeArgs('countLatestMiniPrograms'); if(dao::isError()) return dao::getError(); - return $result; } @@ -68,7 +49,6 @@ class aiappModelTest extends baseTest { $result = $this->instance->saveMiniProgramMessage($appID, $type, $content); if(dao::isError()) return dao::getError(); - return $result; } @@ -83,12 +63,8 @@ class aiappModelTest extends baseTest */ public function deleteHistoryMessagesByIDTest($appID, $userID, $messageIDs) { - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('deleteHistoryMessagesByID'); - $method->setAccessible(true); - $method->invoke($this->instance, $appID, $userID, $messageIDs); + $this->invokeArgs('deleteHistoryMessagesByID', [$appID, $userID, $messageIDs]); if(dao::isError()) return dao::getError(); - return true; } @@ -104,7 +80,6 @@ class aiappModelTest extends baseTest { $result = $this->instance->getHistoryMessages($appID, $limit); if(dao::isError()) return dao::getError(); - return $result; } @@ -120,7 +95,6 @@ class aiappModelTest extends baseTest { $result = $this->instance->getCollectedMiniProgramIDs($userID, $pager); if(dao::isError()) return dao::getError(); - return $result; } @@ -136,7 +110,6 @@ class aiappModelTest extends baseTest { $result = $this->instance->getSquareCategoryArray($collectedIDs, $latestSum); if(dao::isError()) return dao::getError(); - return $result; } @@ -150,7 +123,6 @@ class aiappModelTest extends baseTest { $result = $this->instance->getUsedCategoryArray(); if(dao::isError()) return dao::getError(); - return $result; } -} \ No newline at end of file +} diff --git a/module/api/test/lib/model.class.php b/module/api/test/lib/model.class.php index cfa4bd38c7..765224d29c 100644 --- a/module/api/test/lib/model.class.php +++ b/module/api/test/lib/model.class.php @@ -19,7 +19,6 @@ class apiModelTest extends baseTest { $result = $this->instance->publishLib($data); if(dao::isError()) return dao::getError(); - return $result; } @@ -846,7 +845,6 @@ class apiModelTest extends baseTest { $result = $this->instance->getPrivApis($mode); if(dao::isError()) return dao::getError(); - return $result; } } diff --git a/module/api/test/lib/zen.class.php b/module/api/test/lib/zen.class.php index d2450b4559..5915a6d53f 100644 --- a/module/api/test/lib/zen.class.php +++ b/module/api/test/lib/zen.class.php @@ -8,563 +8,6 @@ class apiZenTest extends baseTest protected $moduleName = 'api'; protected $className = 'zen'; - /** - * Test publish a lib. - * - * @param object $data - * @access public - * @return mixed - */ - public function publishLibTest($data) - { - $result = $this->objectModel->publishLib($data); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test delete a release. - * - * @param int $id - * @param int $libID - * @access public - * @return object - */ - public function deleteReleaseTest($id, $libID = 0) - { - $this->objectModel->deleteRelease($id); - - $objects = $this->objectModel->getRelease($libID); - - if(dao::isError()) return dao::getError(); - - return $objects; - } - - /** - * Test getApiStatusText method. - * - * @param string $status - * @access public - * @return string - */ - public function getApiStatusTextTest($status) - { - $result = $this->objectModel->getApiStatusText($status); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test create a api. - * - * @param array $params - * @param bool $confirm - * @access public - * @return object - */ - public function createTest($params, $confirm = true) - { - global $tester; - - $_POST = $params; - $objects = $this->objectModel->create($params['lib']); - - if(dao::isError()) return dao::getError(); - - if($confirm) $tester->dao->delete()->from(TABLE_API)->where('id')->eq($objects->id)->exec(); - - return $objects; - } - - /** - * Test create a data struct. - * - * @param object $data - * @access public - * @return mixed - */ - public function createStructTest($data) - { - $result = $this->objectModel->createStruct($data); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test update a data struct. - * - * @param object $formData - * @access public - * @return mixed - */ - public function updateStructTest($formData) - { - $result = $this->objectModel->updateStruct($formData); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test update a api. - * - * @param int $apiID - * @param array $params - * @param bool $confirm - * @access public - * @return object - */ - public function updateTest($apiID, $params, $confirm = true) - { - global $tester; - $_POST = $params; - - $objects = $this->objectModel->update($apiID); - - if(dao::isError()) return dao::getError(); - - if($confirm) $tester->dao->delete()->from(TABLE_API)->where('id')->eq($apiID)->exec(); - - return $objects; - } - - /** - * Test get data struct list by libID. - * - * @param int $id - * @param bool $confirm - * @access public - * @return object - */ - public function getStructListByLibIDTest($id, $confirm = true) - { - global $tester; - - $objects = $this->objectModel->getStructListByLibID($id); - - if(dao::isError()) return dao::getError(); - - if($confirm) $tester->dao->delete()->from(TABLE_APISTRUCT)->where('id')->eq($objects['0']->id)->exec(); - - return $objects; - } - - /** - * Test get a data struct by ID. - * - * @param int $id - * @param bool $confirm - * @access public - * @return object - */ - public function getStructByIDTest($id, $confirm = true) - { - global $tester; - - $objects = $this->objectModel->getStructByID($id); - - if(dao::isError()) return dao::getError(); - - if($confirm) $tester->dao->delete()->from(TABLE_APISTRUCT)->where('id')->eq($objects->id)->exec(); - - return $objects; - } - - /** - * Test get release by libID. - * - * @param int $libID - * @param string $type - * @param int $params - * @param bool $confirm - * @access public - * @return object - */ - public function getReleaseTest($libID = 0, $type = '', $param = 0, $confirm = true) - { - $objects = $this->objectModel->getRelease($libID = 0, $type = '', $param = 0); - - if(dao::isError()) return dao::getError(); - - if($confirm) $this->objectModel->deleteRelease($objects->id); - - return $objects; - } - - /** - * Test get release list by api. - * - * @param int $libID - * @param int $id - * @param bool $confirm - * @access public - * @return object - */ - public function getReleaseListByApiTest($libID, $id = 0, $confirm = true) - { - $objects = $this->objectModel->getReleaseListByApi($libID); - - if(dao::isError()) return dao::getError(); - - if($confirm) $this->objectModel->deleteRelease($objects[$id]->id); - - return $objects[$id]; - } - - /** - * Test get lib by ID. - * - * @param int $id - * @param int $version - * @param int $release - * @access public - * @return object - */ - public function getLibByIdTest($id, $version = 0, $release = 0) - { - $objects = $this->objectModel->getLibById($id, $version = 0, $release = 0); - - if(dao::isError()) return dao::getError(); - - return $objects; - } - - /** - * Test get lib by ID. - * - * @param int $id - * @param int $version - * @param int $release - * @access public - * @return object - */ - public function getApiListByReleaseTest($release, $where = '1 = 1 ') - { - global $tester; - - $objects = $this->objectModel->getApiListByRelease($release, $where = '1 = 1 '); - - if(dao::isError()) return dao::getError(); - - foreach($release->snap['apis'] as $api) $tester->dao->delete()->from(TABLE_API)->where('id')->eq($api['id'])->exec(); - $this->objectModel->deleteRelease($release->id); - - return $objects; - } - - /** - * Test get list by module ID. - * - * @param int $libID - * @param int $moduleID - * @param int $release - * @access public - * @return void - */ - public function getListByModuleIdTest($libID = 0, $moduleID = 0, $release = 0) - { - $objects = $this->objectModel->getListByModuleId($libID, $moduleID, $release); - - if(dao::isError()) return dao::getError(); - - return current($objects); - } - - /** - * Test get struct list by release. - * - * @param object $release - * @param string $where - * @param string $orderBy - * @access public - * @return object - */ - public function getStructListByReleaseTest($release, $where = '1 = 1 ', $orderBy = 'id') - { - $objects = $this->objectModel->getStructListByRelease($release, $where = '1 = 1 ', $orderBy = 'id'); - - if(dao::isError()) return dao::getError(); - - return $objects; - } - - /** - * Test createDemoLib method. - * - * @param string $name - * @param string $baseUrl - * @param string $currentAccount - * @access public - * @return object|false - */ - public function createDemoLibTest($name, $baseUrl, $currentAccount) - { - global $tester; - - $reflection = new ReflectionClass($this->objectModel); - $method = $reflection->getMethod('createDemoLib'); - $method->setAccessible(true); - - $libID = $method->invoke($this->objectModel, $name, $baseUrl, $currentAccount); - - if(dao::isError()) return dao::getError(); - - $lib = $tester->dao->select('*')->from(TABLE_DOCLIB)->where('id')->eq($libID)->fetch(); - - $tester->dao->delete()->from(TABLE_DOCLIB)->where('id')->eq($libID)->exec(); - - return $lib; - } - - /** - * Test createDemoStruct method. - * - * @param int $libID - * @param string $version - * @param string $currentAccount - * @access public - * @return mixed - */ - public function createDemoStructTest($libID, $version, $currentAccount) - { - global $tester; - - $reflection = new ReflectionClass($this->objectModel); - $method = $reflection->getMethod('createDemoStruct'); - $method->setAccessible(true); - - $result = $method->invoke($this->objectModel, $libID, $version, $currentAccount); - - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test createDemoStructSpec method. - * - * @param string $version - * @param string $currentAccount - * @access public - * @return mixed - */ - public function createDemoStructSpecTest($version, $currentAccount) - { - global $tester; - - $reflection = new ReflectionClass($this->objectModel); - $method = $reflection->getMethod('createDemoStructSpec'); - $method->setAccessible(true); - - $result = $method->invoke($this->objectModel, $version, $currentAccount); - - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test createDemoModule method. - * - * @param int $libID - * @param string $version - * @access public - * @return mixed - */ - public function createDemoModuleTest($libID, $version) - { - global $tester; - - $reflection = new ReflectionClass($this->objectModel); - $method = $reflection->getMethod('createDemoModule'); - $method->setAccessible(true); - - $result = $method->invoke($this->objectModel, $libID, $version); - - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test createDemoApi method. - * - * @param int $libID - * @param string $version - * @param array $moduleMap - * @param string $currentAccount - * @access public - * @return mixed - */ - public function createDemoApiTest($libID, $version, $moduleMap, $currentAccount) - { - global $tester; - - $reflection = new ReflectionClass($this->objectModel); - $method = $reflection->getMethod('createDemoApi'); - $method->setAccessible(true); - - $result = $method->invoke($this->objectModel, $libID, $version, $moduleMap, $currentAccount); - - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test createDemoApiSpec method. - * - * @param string $version - * @param array $apiMap - * @param array $moduleMap - * @param string $currentAccount - * @access public - * @return mixed - */ - public function createDemoApiSpecTest($version, $apiMap, $moduleMap, $currentAccount) - { - global $tester; - - try - { - // 先检查版本文件是否存在,避免后续的file_get_contents错误 - $demoDataFile = $this->objectModel->app->getAppRoot() . 'db' . DS . 'api' . DS . $version . DS . 'apispec'; - if (!file_exists($demoDataFile)) { - return 0; - } - - $reflection = new ReflectionClass($this->objectModel); - $method = $reflection->getMethod('createDemoApiSpec'); - $method->setAccessible(true); - - $result = $method->invoke($this->objectModel, $version, $apiMap, $moduleMap, $currentAccount); - - if(dao::isError()) return dao::getError(); - - return $result ? 1 : 0; - } - catch(Exception $e) - { - return 0; - } - catch(TypeError $e) - { - return 0; - } - } - - /** - * Test getGroupedObjects method. - * - * @access public - * @return array - */ - public function getGroupedObjectsTest() - { - $result = $this->objectModel->getGroupedObjects(); - - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test buildSearchForm method. - * - * @param object $lib - * @param int $queryID - * @param string $actionURL - * @param array $libs - * @param string $type - * @access public - * @return mixed - */ - public function buildSearchFormTest($lib, $queryID, $actionURL, $libs = array(), $type = '') - { - global $tester; - - // 备份原始配置 - $originalConfig = isset($tester->config->api->search) ? $tester->config->api->search : null; - - // 执行方法 - $this->objectModel->buildSearchForm($lib, $queryID, $actionURL, $libs, $type); - - if(dao::isError()) return dao::getError(); - - // 返回设置后的搜索配置 - $result = array( - 'module' => isset($tester->config->api->search['module']) ? $tester->config->api->search['module'] : '', - 'queryID' => isset($tester->config->api->search['queryID']) ? $tester->config->api->search['queryID'] : '', - 'actionURL' => isset($tester->config->api->search['actionURL']) ? $tester->config->api->search['actionURL'] : '', - 'libValues' => isset($tester->config->api->search['params']['lib']['values']) ? $tester->config->api->search['params']['lib']['values'] : array() - ); - - // 恢复原始配置 - if($originalConfig !== null) $tester->config->api->search = $originalConfig; - - return $result; - } - - /** - * Test getApiSpecByData method. - * - * @param object $data - * @access public - * @return array - */ - public function getApiSpecByDataTest($data) - { - $reflection = new ReflectionClass($this->objectModel); - $method = $reflection->getMethod('getApiSpecByData'); - $method->setAccessible(true); - - $result = $method->invoke($this->objectModel, $data); - - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test getApiStructSpecByData method. - * - * @param object $data - * @access public - * @return array - */ - public function getApiStructSpecByDataTest($data) - { - $reflection = new ReflectionClass($this->objectModel); - $method = $reflection->getMethod('getApiStructSpecByData'); - $method->setAccessible(true); - - $result = $method->invoke($this->objectModel, $data); - - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test getTypeList method. - * - * @param int $libID - * @access public - * @return array - */ - public function getTypeListTest($libID) - { - $result = $this->objectModel->getTypeList($libID); - - if(dao::isError()) return dao::getError(); - - return $result; - } - /** * Test generateLibsDropMenu method. * @@ -575,31 +18,8 @@ class apiZenTest extends baseTest */ public function generateLibsDropMenuTest($lib, $version = 0) { - global $tester; - - // 加载api控制器类、模型类和apiZen类 - require_once dirname(__FILE__, 3) . '/control.php'; - require_once dirname(__FILE__, 3) . '/model.php'; - require_once dirname(__FILE__, 3) . '/zen.php'; - - // 创建apiZen实例 - $apiZen = new apiZen(); - - // 为apiZen对象注入必要的依赖 - $apiZen->config = $tester->config; - $apiZen->session = $tester->session; - $apiZen->app = $tester->app; - $apiZen->lang = $tester->lang; - - // 使用反射调用protected方法 - $reflection = new ReflectionClass($apiZen); - $method = $reflection->getMethod('generateLibsDropMenu'); - $method->setAccessible(true); - - $result = $method->invoke($apiZen, $lib, $version); - + $result = $this->invokeArgs('generateLibsDropMenu', [$lib, $version]); if(dao::isError()) return dao::getError(); - return $result; } @@ -613,112 +33,14 @@ class apiZenTest extends baseTest * @param int $moduleID * @param string $spaceType * @param int $release - * @param string $cookieData * @access public * @return array */ - public function parseDocSpaceParamTest(array $libs, int $libID, string $type, int $objectID, int $moduleID, string $spaceType, int $release, string $cookieData = '') + public function parseDocSpaceParamTest(array $libs, int $libID, string $type, int $objectID, int $moduleID, string $spaceType, int $release) { - global $tester; - - // 加载api控制器类、模型类和apiZen类 - require_once dirname(__FILE__, 3) . '/control.php'; - require_once dirname(__FILE__, 3) . '/model.php'; - require_once dirname(__FILE__, 3) . '/zen.php'; - - // 创建apiZen实例并模拟cookie属性 - $apiZen = new apiZen(); - - // 为apiZen对象注入必要的依赖 - $apiZen->config = $tester->config; - $apiZen->session = $tester->session; - $apiZen->app = $tester->app; - $apiZen->lang = $tester->lang; - - // 创建cookie对象 - $apiZen->cookie = new stdClass(); - if(!empty($cookieData)) - { - $apiZen->cookie->docSpaceParam = $cookieData; - } - - // 创建view对象 - $apiZen->view = new stdClass(); - - // 模拟doc模块以避免复杂的依赖关系 - $apiZen->doc = new stdClass(); - $apiZen->doc->setMenuByType = function($type, $objectID, $libID) use ($libs) { - $object = null; - $objectDropdown = array(); - return array($libs, $libID, $object, $objectID, $objectDropdown); - }; - $apiZen->doc->getLibTree = function($libID, $libs, $type, $moduleID = 0, $objectID = 0, $browseType = '', $param = '') { - return array('tree' => 'mock_tree_data'); - }; - - // 模拟generateLibsDropMenu方法 - $reflection = new ReflectionClass($apiZen); - $generateMethod = $reflection->getMethod('generateLibsDropMenu'); - $generateMethod->setAccessible(true); - - // 使用反射调用protected方法parseDocSpaceParam - $method = $reflection->getMethod('parseDocSpaceParam'); - $method->setAccessible(true); - - // 简单的测试:仅检查方法是否能正常设置view属性 - try { - // 先模拟简单场景避免复杂依赖 - if(!empty($cookieData)) { - $docParam = json_decode($cookieData); - if(isset($docParam) && !(in_array($docParam->type, array('product', 'project')) && $docParam->objectID == 0)) { - // 直接设置结果,模拟方法行为 - $apiZen->view->type = $docParam->type; - $apiZen->view->objectType = $docParam->type; - $apiZen->view->objectID = $docParam->objectID; - $apiZen->view->libID = $docParam->libID; - $apiZen->view->moduleID = $docParam->moduleID; - $apiZen->view->spaceType = $docParam->type; - $apiZen->view->libTree = array('mock' => true); - $apiZen->view->objectDropdown = array('mock' => true); - } else { - // 默认情况 - $apiZen->view->type = $type; - $apiZen->view->objectType = $type; - $apiZen->view->objectID = $objectID; - $apiZen->view->libID = $libID; - $apiZen->view->moduleID = $moduleID; - $apiZen->view->spaceType = $spaceType; - $apiZen->view->libTree = array('mock' => true); - $apiZen->view->objectDropdown = array('mock' => true); - } - } else { - // 默认情况 - $apiZen->view->type = $type; - $apiZen->view->objectType = $type; - $apiZen->view->objectID = $objectID; - $apiZen->view->libID = $libID; - $apiZen->view->moduleID = $moduleID; - $apiZen->view->spaceType = $spaceType; - $apiZen->view->libTree = array('mock' => true); - $apiZen->view->objectDropdown = array('mock' => true); - } - } catch (Exception $e) { - return array('error' => $e->getMessage()); - } - + $this->invokeArgs('parseDocSpaceParam', [$libs, $libID, $type, $objectID, $moduleID, $spaceType, $release]); if(dao::isError()) return dao::getError(); - - // 返回view中设置的属性 - return array( - 'type' => isset($apiZen->view->type) ? $apiZen->view->type : '', - 'objectType' => isset($apiZen->view->objectType) ? $apiZen->view->objectType : '', - 'objectID' => isset($apiZen->view->objectID) ? $apiZen->view->objectID : 0, - 'libID' => isset($apiZen->view->libID) ? $apiZen->view->libID : 0, - 'moduleID' => isset($apiZen->view->moduleID) ? $apiZen->view->moduleID : 0, - 'spaceType' => isset($apiZen->view->spaceType) ? $apiZen->view->spaceType : '', - 'libTree' => isset($apiZen->view->libTree) && !empty($apiZen->view->libTree), - 'objectDropdown' => isset($apiZen->view->objectDropdown) && !empty($apiZen->view->objectDropdown) - ); + return $this->getProperty('view'); } /** @@ -731,36 +53,9 @@ class apiZenTest extends baseTest */ public function getMethodTest(string $filePath, string $ext = '') { - global $tester; - - // 加载api控制器类、模型类和apiZen类 - require_once dirname(__FILE__, 3) . '/control.php'; - require_once dirname(__FILE__, 3) . '/model.php'; - require_once dirname(__FILE__, 3) . '/zen.php'; - - // 创建apiZen实例 - $apiZen = new apiZen(); - - // 为apiZen对象注入必要的依赖 - $apiZen->config = $tester->config; - $apiZen->session = $tester->session; - $apiZen->app = $tester->app; - $apiZen->lang = $tester->lang; - - // 使用反射调用protected方法 - $reflection = new ReflectionClass($apiZen); - $method = $reflection->getMethod('getMethod'); - $method->setAccessible(true); - - try { - $result = $method->invoke($apiZen, $filePath, $ext); - if(dao::isError()) return dao::getError(); - return $result; - } catch (Exception $e) { - return array('error' => $e->getMessage()); - } catch (ReflectionException $e) { - return array('error' => 'ReflectionException: ' . $e->getMessage()); - } + $result = $this->invokeArgs('getMethod', [$filePath, $ext]); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -773,80 +68,10 @@ class apiZenTest extends baseTest * @access public * @return array */ - public function requestTest(string $moduleName, string $methodName, string $action, array $postData = array()) + public function requestTest(string $moduleName, string $methodName, string $action) { - global $tester; - - // 加载api控制器类、模型类和apiZen类 - require_once dirname(__FILE__, 3) . '/control.php'; - require_once dirname(__FILE__, 3) . '/model.php'; - require_once dirname(__FILE__, 3) . '/zen.php'; - - // 创建apiZen实例 - $apiZen = new apiZen(); - - // 为apiZen对象注入必要的依赖 - $apiZen->config = $tester->config; - $apiZen->session = $tester->session; - $apiZen->app = $tester->app; - $apiZen->lang = $tester->lang; - - // 备份原始 $_POST 数据 - $originalPost = $_POST; - - // 设置测试用的 $_POST 数据 - $_POST = $postData; - - // 模拟 URL 构建过程,不实际调用 file_get_contents - $host = 'http://localhost'; // 模拟系统URL - $param = ''; - - if($action == 'extendModel') - { - if(!isset($_POST['noparam'])) - { - foreach($_POST as $key => $value) $param .= ',' . $key . '=' . $value; - $param = ltrim($param, ','); - } - $url = $host . "/api-getModel-moduleName=$moduleName&methodName=$methodName¶ms=$param.json"; - $url .= strpos($url, '?') === false ? '?' : '&'; - $url .= 'zentaosid=test_session_id'; - } - else - { - if(!isset($_POST['noparam'])) - { - foreach($_POST as $key => $value) $param .= '&' . $key . '=' . $value; - $param = ltrim($param, '&'); - } - $url = $host . "/$moduleName-$methodName" . ($param ? "-$param" : '') . ".json"; - $url .= strpos($url, '?') === false ? '?' : '&'; - $url .= 'zentaosid=test_session_id'; - } - - // 模拟响应内容,不实际进行HTTP请求 - $content = 'mock_response_content'; - - // 恢复原始 $_POST 数据 - $_POST = $originalPost; - + $result = $this->invokeArgs('request', [$moduleName, $methodName, $action]); if(dao::isError()) return dao::getError(); - - return array('url' => $url, 'content' => $content); - } - - /** - * Test getPrivApis method. - * - * @param string $mode - * @access public - * @return array - */ - public function getPrivApisTest($mode = '') - { - $result = $this->objectModel->getPrivApis($mode); - if(dao::isError()) return dao::getError(); - return $result; } } diff --git a/module/backup/test/lib/model.class.php b/module/backup/test/lib/model.class.php index 6913c256b9..b5f51efb30 100644 --- a/module/backup/test/lib/model.class.php +++ b/module/backup/test/lib/model.class.php @@ -19,7 +19,6 @@ class backupModelTest extends baseTest { $result = $this->instance->backSQL($backupFile); if(dao::isError()) return dao::getError(); - return $result; } @@ -34,7 +33,6 @@ class backupModelTest extends baseTest { $result = $this->instance->backFile($backupFile); if(dao::isError()) return dao::getError(); - return $result; } @@ -49,7 +47,6 @@ class backupModelTest extends baseTest { $result = $this->instance->backCode($backupFile); if(dao::isError()) return dao::getError(); - return $result; } @@ -97,7 +94,6 @@ class backupModelTest extends baseTest { $result = $this->instance->restoreFile($backupFile); if(dao::isError()) return dao::getError(); - return $result; } @@ -112,7 +108,6 @@ class backupModelTest extends baseTest { $result = $this->instance->getDiskSpace($backupPath); if(dao::isError()) return dao::getError(); - return $result; } @@ -130,7 +125,6 @@ class backupModelTest extends baseTest $result = $this->instance->getDirSize($dir); if(dao::isError()) return dao::getError(); - return $result; } @@ -239,271 +233,6 @@ class backupModelTest extends baseTest return array('result' => 'success'); } - /** - * Test backupCode method for zen layer. - * - * @param string $fileName - * @param string $reload - * @access public - * @return mixed - */ - public function backupCodeZenTest($fileName = null, $reload = 'no') - { - global $tester; - $objectTao = $tester->loadTao('backup'); - - // Mock implementation to simulate backupCode behavior - if(empty($fileName)) - { - $fileName = 'test_backup_code_' . time(); - } - - // Mock different scenarios based on input - if($fileName === 'fail_test') - { - if($reload === 'yes') - { - return array('result' => 'fail', 'message' => 'Mock code backup failed'); - } - else - { - return array('result' => 'fail', 'message' => 'Mock code backup failed'); - } - } - - // Mock nofile setting check - if nofile is in config, skip code backup - if(isset($this->instance->config->backup->setting) && str_contains($this->instance->config->backup->setting, 'nofile')) - { - return array('result' => 'success'); - } - - // Mock backCode method call result - $mockResult = new stdClass(); - $mockResult->result = true; - $mockResult->error = ''; - - // Simulate failure scenario for specific test cases - if($fileName === 'invalid_path') - { - $mockResult->result = false; - $mockResult->error = 'Invalid backup path'; - return array('result' => 'fail', 'message' => sprintf('备份代码失败: %s', $mockResult->error)); - } - - // Return success for normal cases - return array('result' => 'success'); - } - - /** - * Test removeExpiredFiles method for zen layer. - * - * @param array $mockFiles - * @param int $mockHoldDays - * @access public - * @return mixed - */ - public function removeExpiredFilesTest($mockFiles = null, $mockHoldDays = 14) - { - global $tester; - - // Mock backup path - $mockBackupPath = sys_get_temp_dir() . '/backup_test_' . time() . '/'; - if(!is_dir($mockBackupPath)) mkdir($mockBackupPath, 0777, true); - - // Create mock backup files with different ages - if($mockFiles === null) - { - $mockFiles = array( - '20240101.sql' => time() - (20 * 24 * 3600), // 20 days ago - expired - '20240110.file' => time() - (10 * 24 * 3600), // 10 days ago - not expired - '20240115.code' => time() - (5 * 24 * 3600), // 5 days ago - not expired - '20240120.sql' => time() - (30 * 24 * 3600), // 30 days ago - expired - 'other.txt' => time() - (10 * 24 * 3600), // non-backup file - should be ignored - ); - } - - // Only create files if mockFiles is not empty - if(!empty($mockFiles)) - { - foreach($mockFiles as $fileName => $fileTime) - { - $filePath = $mockBackupPath . $fileName; - touch($filePath, $fileTime); - } - } - - // Mock zen object behavior - $mockZen = new stdClass(); - $mockZen->backupPath = $mockBackupPath; - $mockZen->config = new stdClass(); - $mockZen->config->backup = new stdClass(); - $mockZen->config->backup->holdDays = $mockHoldDays; - - // Simulate removeExpiredFiles method logic - $backupFiles = glob("{$mockZen->backupPath}*.*"); - if(empty($backupFiles)) - { - $this->cleanupTestDir($mockBackupPath); - return array('removed' => 0, 'kept' => 0); - } - - $time = time(); - $removed = 0; - $kept = 0; - - foreach($backupFiles as $file) - { - $fileName = basename($file); - if(!preg_match('/[0-9]+\.(sql|file|code)/', $fileName)) - { - // Non-backup files are ignored in the logic, not counted in kept - continue; - } - - $fileAge = $time - filemtime($file); - $holdSeconds = $mockZen->config->backup->holdDays * 24 * 3600; - - if($fileAge > $holdSeconds) - { - unlink($file); // Remove expired file - $removed++; - } - else - { - $kept++; // Keep non-expired file - } - } - - $this->cleanupTestDir($mockBackupPath); - return array('removed' => $removed, 'kept' => $kept); - } - - /** - * Test restoreSQL method for zen layer. - * - * @param string $fileName - * @access public - * @return mixed - */ - public function restoreSQLZenTest($fileName = null) - { - global $tester; - $objectTao = $tester->loadTao('backup'); - - // Mock implementation to simulate restoreSQL behavior - if(empty($fileName)) - { - return array('result' => 'success'); - } - - // Mock different scenarios based on fileName - these should fail - if($fileName === 'nonexistent') - { - return array('result' => 'fail', 'message' => '数据库还原失败,错误:备份文件不存在'); - } - - if($fileName === 'corrupted') - { - return array('result' => 'fail', 'message' => '数据库还原失败,错误:备份文件格式错误'); - } - - if($fileName === 'permission_denied') - { - return array('result' => 'fail', 'message' => '数据库还原失败,错误:权限不足'); - } - - if($fileName === 'invalid_format') - { - return array('result' => 'fail', 'message' => '数据库还原失败,错误:SQL文件格式无效'); - } - - if($fileName === 'restore_fail_test') - { - return array('result' => 'fail', 'message' => '数据库还原失败,错误:Mock restoration failed'); - } - - // For normal cases, first check if backup file exists using mock logic - // Since we can't actually call getBackupFile without real backup files, mock this behavior - - // Mock that test_backup has a corresponding backup file - if($fileName === 'test_backup') - { - // Mock successful restoration - return array('result' => 'success'); - } - - // For other cases, mock as no backup file found (return success as per original zen method) - return array('result' => 'success'); - } - - /** - * Test restoreFile method for zen layer. - * - * @param string $fileName - * @access public - * @return mixed - */ - public function restoreFileZenTest($fileName = null) - { - if(is_null($fileName)) return array('result' => 'fail', 'message' => '文件名不能为空'); - - if($fileName === 'invalid_format') - { - return array('result' => 'fail', 'message' => '附件还原失败,错误:文件格式无效'); - } - - if($fileName === 'restore_fail_test') - { - return array('result' => 'fail', 'message' => '附件还原失败,错误:Mock restoration failed'); - } - - // For normal cases, mock successful restoration - if($fileName === 'test_backup') - { - return array('result' => 'success'); - } - - // For other cases, mock as no backup file found (return success as per original zen method) - return array('result' => 'success'); - } - - /** - * Test setHoldDays method for zen layer. - * - * @param object $data - * @access public - * @return mixed - */ - public function setHoldDaysTest($data = null) - { - // Mock implementation based on setHoldDays logic in zen.php - if(is_null($data)) - { - $data = new stdClass(); - $data->holdDays = 14; - } - - // Simulate dao::$errors reset - dao::$errors = array(); - - // Check if holdDays is empty (but 0 is not considered empty in this context) - if(empty($data->holdDays) && $data->holdDays !== 0) - { - dao::$errors['holdDays'] = '『保留天数』不能为空。'; - return dao::$errors; - } - - // Check if holdDays is a positive integer - if(!preg_match("/^-?\d+$/", (string)$data->holdDays) || $data->holdDays <= 0) - { - dao::$errors['holdDays'] = '『保留天数』应当是正整数。'; - return dao::$errors; - } - - // Mock successful setting save - return true; - } - /** * Test addFileHeader method. * @@ -515,7 +244,6 @@ class backupModelTest extends baseTest { $result = $this->instance->addFileHeader($fileName); if(dao::isError()) return dao::getError(); - return $result; } @@ -530,7 +258,6 @@ class backupModelTest extends baseTest { $result = $this->instance->getBackupDirProgress($backup); if(dao::isError()) return dao::getError(); - return $result; } @@ -544,7 +271,6 @@ class backupModelTest extends baseTest { $result = $this->instance->getBackupPath(); if(dao::isError()) return dao::getError(); - return $result; } @@ -559,7 +285,6 @@ class backupModelTest extends baseTest { $result = $this->instance->getTmpLogFile($backupFile); if(dao::isError()) return dao::getError(); - return $result; } @@ -574,7 +299,6 @@ class backupModelTest extends baseTest { $result = $this->instance->processFileSize($fileSize); if(dao::isError()) return dao::getError(); - return $result; } @@ -594,7 +318,6 @@ class backupModelTest extends baseTest { $result = $this->instance->processSummary($file, $count, $size, $errorFiles, $allCount, $action); if(dao::isError()) return dao::getError(); - return $result; } @@ -609,7 +332,6 @@ class backupModelTest extends baseTest { $result = $this->instance->removeFileHeader($fileName); if(dao::isError()) return dao::getError(); - return $result; } @@ -631,4 +353,4 @@ class backupModelTest extends baseTest } rmdir($dir); } -} \ No newline at end of file +} diff --git a/module/bi/test/lib/model.class.php b/module/bi/test/lib/model.class.php index eed3dbfc82..80e6416769 100644 --- a/module/bi/test/lib/model.class.php +++ b/module/bi/test/lib/model.class.php @@ -57,42 +57,9 @@ class biModelTest extends baseTest */ public function buildQueryResultTableColumnsTest($fieldSettings) { - try - { - $result = $this->instance->buildQueryResultTableColumns($fieldSettings); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 如果出现数据库连接问题,模拟方法的行为 - return $this->mockBuildQueryResultTableColumns($fieldSettings); - } - } - - /** - * Mock buildQueryResultTableColumns method for testing. - * - * @param array $fieldSettings - * @access private - * @return array - */ - private function mockBuildQueryResultTableColumns($fieldSettings) - { - $cols = array(); - $clientLang = 'zh-cn'; // 模拟默认语言 - - foreach($fieldSettings as $field => $settings) - { - $settings = (array)$settings; - $title = isset($settings[$clientLang]) ? $settings[$clientLang] : $field; - $type = $settings['type']; - - $cols[] = array('name' => $field, 'title' => $title, 'sortType' => false); - } - - return $cols; + $result = $this->instance->buildQueryResultTableColumns($fieldSettings); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -164,68 +131,16 @@ class biModelTest extends baseTest */ public function getColumnsTest($sql, $driver = 'mysql', $returnOrigin = false) { - try - { - // 处理空SQL情况 - if(empty($sql)) return 0; + if(empty($sql)) return 0; - // 测试无效驱动 - if($driver == 'invaliddriver') return 0; + // 尝试实际调用(如果测试环境允许) + $result = $this->instance->getColumns($sql, $driver, $returnOrigin); + if(dao::isError()) return dao::getError(); - // 模拟原始返回模式 - if($returnOrigin) return 'returnOrigin'; + // 处理无效驱动的情况 + if($result === false) return 0; - // 模拟不同SQL查询的返回结果,避免实际数据库连接问题 - if(strpos($sql, 'select id, name from zt_product') !== false) - { - return array( - 'id' => array('name' => 'id', 'native_type' => 'INT24'), - 'name' => array('name' => 'name', 'native_type' => 'VAR_STRING') - ); - } - - if(strpos($sql, 'select id, name, code') !== false) - { - $result = array( - 'id' => array('name' => 'id', 'native_type' => 'INT24'), - 'name' => array('name' => 'name', 'native_type' => 'VAR_STRING'), - 'code' => array('name' => 'code', 'native_type' => 'VAR_STRING') - ); - // 对于步骤5,返回数组长度 - return count($result); - } - - if(strpos($sql, 'select id, title from zt_bug') !== false) - { - return array( - 'id' => array('name' => 'id', 'native_type' => 'INT24'), - 'title' => array('name' => 'title', 'native_type' => 'VAR_STRING') - ); - } - - // 对于其他复杂查询的模拟 - if(strpos($sql, 'join') !== false) - { - return array( - 'id' => array('name' => 'id', 'native_type' => 'INT24'), - 'name' => array('name' => 'name', 'native_type' => 'VAR_STRING'), - 'title' => array('name' => 'title', 'native_type' => 'VAR_STRING') - ); - } - - // 尝试实际调用(如果测试环境允许) - $result = $this->instance->getColumns($sql, $driver, $returnOrigin); - if(dao::isError()) return dao::getError(); - - // 处理无效驱动的情况 - if($result === false) return 0; - - return $result; - } - catch(Exception $e) - { - return 0; - } + return $result; } /** @@ -233,12 +148,13 @@ class biModelTest extends baseTest * * @param string $sql * @access public - * @return array + * @return array|false */ public function getTableAndFields($sql) { - // 总是使用mock模式,确保测试稳定 - return $this->mockGetTableAndFields($sql); + $result = $this->instance->getTableAndFields($sql); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -262,80 +178,6 @@ class biModelTest extends baseTest return $result; } - /** - * Mock getTableAndFields method for testing. - * - * @param string $sql - * @access private - * @return array|int - */ - private function mockGetTableAndFields($sql) - { - // 处理无效SQL - if(empty($sql) || !is_string($sql)) return 0; - - $sql = trim($sql); - - // 检查是否是有效的SELECT语句 - if(stripos($sql, 'SELECT') !== 0) return 0; - - // 特殊处理:无效SQL语句 - if($sql === 'INVALID SQL STATEMENT') return 0; - - // 处理各种SQL语句 - $tables = array(); - $fields = array(); - - // 处理: SELECT id, name FROM zt_user - if(preg_match('/SELECT\s+(.+?)\s+FROM\s+(\S+)/i', $sql, $matches)) - { - $fieldsList = trim($matches[1]); - $tableName = trim($matches[2]); - - // 解析表名 - if(preg_match('/^(\w+)/', $tableName, $tableMatch)) - { - $tables[] = $tableMatch[1]; - } - - // 解析字段 - if($fieldsList === '*') - { - // 处理SELECT * - $fields['*'] = '*'; - } - else - { - // 处理具体字段 - $fieldsArray = explode(',', $fieldsList); - foreach($fieldsArray as $field) - { - $field = trim($field); - // 移除表别名前缀(如 u.id -> id) - if(strpos($field, '.') !== false) - { - $field = substr($field, strpos($field, '.') + 1); - } - $fields[$field] = $field; - } - } - } - - // 处理连接查询: SELECT u.id, p.name FROM zt_user u LEFT JOIN zt_project p ON ... - if(preg_match('/FROM\s+(\w+)\s+\w+\s+.*?JOIN\s+(\w+)/i', $sql, $joinMatches)) - { - $tables = array($joinMatches[1], $joinMatches[2]); - } - - // 处理子查询: SELECT * FROM (SELECT id FROM zt_user) sub - if(preg_match('/FROM\s*\(.*?FROM\s+(\w+).*?\)/i', $sql, $subMatches)) - { - $tables = array($subMatches[1]); - } - - return array('tables' => array_unique($tables), 'fields' => $fields); - } - /** * Test process vars. * @@ -371,85 +213,9 @@ class biModelTest extends baseTest */ public function prepareBuiltinChartSQLTest($operate) { - global $config; - - // 模拟配置加载 - if(!isset($config->bi)) - { - include dirname(__FILE__, 3) . '/config.php'; - include dirname(__FILE__, 3) . '/config/charts.php'; - } - - $charts = $config->bi->builtin->charts; - - $chartSQLs = array(); - foreach($charts as $chart) - { - $currentOperate = $operate; - $chart = (object)$chart; - $chart->mode = 'text'; - - // JSON编码处理 - if(isset($chart->settings)) $chart->settings = json_encode($chart->settings); - if(isset($chart->filters)) $chart->filters = json_encode($chart->filters); - if(isset($chart->fields)) $chart->fields = json_encode($chart->fields); - if(isset($chart->langs)) $chart->langs = json_encode($chart->langs); - if(!isset($chart->driver)) $chart->driver = 'mysql'; - - // 模拟数据库查询检查记录是否存在 - $exists = false; // 对于测试,假设都不存在 - if(!$exists) $currentOperate = 'insert'; - - $stmt = null; - if($currentOperate == 'insert') - { - $chart->createdBy = 'system'; - $chart->createdDate = date('Y-m-d H:i:s'); - $chart->group = 0; // 模拟getCorrectGroup返回值 - - // 生成模拟的插入SQL - $chartSQLs[] = sprintf( - "INSERT INTO `zt_chart` (`id`, `name`, `code`, `dimension`, `type`, `group`, `sql`, `settings`, `filters`, `stage`, `builtin`, `mode`, `driver`, `createdBy`, `createdDate`) VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')", - $chart->id, - addslashes($chart->name), - addslashes($chart->code), - $chart->dimension, - $chart->type, - $chart->group, - addslashes($chart->sql), - addslashes($chart->settings), - addslashes($chart->filters), - $chart->stage, - $chart->builtin, - $chart->mode, - $chart->driver, - $chart->createdBy, - $chart->createdDate - ); - } - if($currentOperate == 'update') - { - $id = $chart->id; - // 生成模拟的更新SQL - $chartSQLs[] = sprintf( - "UPDATE `zt_chart` SET `name` = '%s', `code` = '%s', `dimension` = '%s', `type` = '%s', `sql` = '%s', `settings` = '%s', `filters` = '%s', `stage` = '%s', `builtin` = '%s', `mode` = '%s', `driver` = '%s' WHERE `id` = %d", - addslashes($chart->name), - addslashes($chart->code), - $chart->dimension, - $chart->type, - addslashes($chart->sql), - addslashes($chart->settings), - addslashes($chart->filters), - $chart->stage, - $chart->builtin, - $chart->mode, - $chart->driver, - $id - ); - } - } - - return $chartSQLs; + $result = $this->instance->prepareBuiltinChartSQL($operate); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -463,7 +229,6 @@ class biModelTest extends baseTest { $result = $this->instance->getViewableObject($objectType); if(dao::isError()) return dao::getError(); - return $result; } @@ -478,10 +243,6 @@ class biModelTest extends baseTest { $result = $this->instance->parseToStatement($sql); if(dao::isError()) return dao::getError(); - - if($result === false) return false; - if(is_object($result)) return 'object'; - return $result; } @@ -495,53 +256,9 @@ class biModelTest extends baseTest */ public function getFieldsTest($statement) { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->instance === null) - { - return $this->mockGetFields($statement); - } - - try - { - $result = $this->instance->getFields($statement); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟getFields方法的行为 - return $this->mockGetFields($statement); - } - } - - /** - * Mock getFields method for testing. - * - * @param object $statement - * @access private - * @return array - */ - private function mockGetFields($statement) - { - if(!$statement->expr) return array(); - - $fields = array(); - foreach($statement->expr as $fieldInfo) - { - $field = $fieldInfo->expr; - $alias = $field; - if(!empty($fieldInfo->alias)) - { - $alias = $fieldInfo->alias; - } - elseif(strrpos($field, '.') !== false) - { - $alias = explode('.', $field)[1]; - } - $fields[$alias] = $field; - } - return $fields; + $result = $this->instance->getFields($statement); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -555,7 +272,6 @@ class biModelTest extends baseTest { $result = $this->instance->parseTableList($sql); if(dao::isError()) return dao::getError(); - return $result; } @@ -568,152 +284,9 @@ class biModelTest extends baseTest */ public function getFieldsWithTableTest($sql) { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->instance === null) - { - return $this->mockGetFieldsWithTable($sql); - } - - try - { - $result = $this->instance->getFieldsWithTable($sql); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟getFieldsWithTable方法的行为 - return $this->mockGetFieldsWithTable($sql); - } - } - - /** - * Mock getFieldsWithTable method for testing. - * - * @param string $sql - * @access private - * @return array - */ - private function mockGetFieldsWithTable($sql) - { - // 处理无效SQL - if(empty($sql) || strpos(strtoupper(trim($sql)), 'SELECT') !== 0) - { - return array(); - } - - // 模拟解析SQL语句 - $sql = trim($sql); - - // 处理: SELECT id, account, realname FROM zt_user - if(preg_match('/SELECT\s+id,\s*account,\s*realname\s+FROM\s+zt_user$/i', $sql)) - { - return array('id' => 'zt_user', 'account' => 'zt_user', 'realname' => 'zt_user'); - } - - // 处理: SELECT u.id, u.account, u.realname FROM zt_user u - if(preg_match('/SELECT\s+u\.id,\s*u\.account,\s*u\.realname\s+FROM\s+zt_user\s+u$/i', $sql)) - { - return array('id' => 'zt_user', 'account' => 'zt_user', 'realname' => 'zt_user'); - } - - // 处理: SELECT u.account, p.name FROM zt_user u LEFT JOIN zt_product p ON u.id = p.id - if(preg_match('/SELECT\s+u\.account,\s*p\.name\s+FROM\s+zt_user\s+u\s+LEFT\s+JOIN\s+zt_product\s+p/i', $sql)) - { - return array('account' => 'zt_user', 'name' => 'zt_product'); - } - - // 处理: SELECT u.account AS user_account, u.realname AS user_name FROM zt_user u - if(preg_match('/SELECT\s+u\.account\s+AS\s+user_account,\s*u\.realname\s+AS\s+user_name\s+FROM\s+zt_user\s+u$/i', $sql)) - { - return array('user_account' => 'zt_user', 'user_name' => 'zt_user'); - } - - // 处理: SELECT * FROM zt_user - if(preg_match('/SELECT\s+\*\s+FROM\s+zt_user$/i', $sql)) - { - // 模拟zt_user表的常见字段 - return array( - 'id' => 'zt_user', - 'account' => 'zt_user', - 'password' => 'zt_user', - 'role' => 'zt_user', - 'realname' => 'zt_user', - 'nickname' => 'zt_user', - 'avatar' => 'zt_user', - 'birthday' => 'zt_user', - 'gender' => 'zt_user', - 'email' => 'zt_user', - 'skype' => 'zt_user', - 'qq' => 'zt_user', - 'yahoo' => 'zt_user', - 'gtalk' => 'zt_user', - 'wangwang' => 'zt_user', - 'mobile' => 'zt_user', - 'phone' => 'zt_user', - 'address' => 'zt_user', - 'zipcode' => 'zt_user', - 'join' => 'zt_user', - 'visits' => 'zt_user', - 'ip' => 'zt_user', - 'last' => 'zt_user', - 'fails' => 'zt_user', - 'locked' => 'zt_user', - 'feedback' => 'zt_user', - 'ranzhi' => 'zt_user', - 'score' => 'zt_user', - 'scoreLevel' => 'zt_user', - 'deleted' => 'zt_user', - 'clientStatus' => 'zt_user', - 'clientLang' => 'zt_user' - ); - } - - // 处理: SELECT u.*, p.name FROM zt_user u INNER JOIN zt_product p ON u.id = p.createdBy - if(preg_match('/SELECT\s+u\.\*,\s*p\.name\s+FROM\s+zt_user\s+u\s+INNER\s+JOIN\s+zt_product\s+p/i', $sql)) - { - // u.*会展开成zt_user表的所有字段,再加上p.name - $userFields = array( - 'id' => 'zt_user', - 'account' => 'zt_user', - 'password' => 'zt_user', - 'role' => 'zt_user', - 'realname' => 'zt_user', - 'nickname' => 'zt_user', - 'avatar' => 'zt_user', - 'birthday' => 'zt_user', - 'gender' => 'zt_user', - 'email' => 'zt_user', - 'skype' => 'zt_user', - 'qq' => 'zt_user', - 'yahoo' => 'zt_user', - 'gtalk' => 'zt_user', - 'wangwang' => 'zt_user', - 'mobile' => 'zt_user', - 'phone' => 'zt_user', - 'address' => 'zt_user', - 'zipcode' => 'zt_user', - 'join' => 'zt_user', - 'visits' => 'zt_user', - 'ip' => 'zt_user', - 'last' => 'zt_user', - 'fails' => 'zt_user', - 'locked' => 'zt_user', - 'feedback' => 'zt_user', - 'ranzhi' => 'zt_user', - 'score' => 'zt_user', - 'scoreLevel' => 'zt_user', - 'deleted' => 'zt_user', - 'clientStatus' => 'zt_user', - 'clientLang' => 'zt_user' - ); - $userFields['name'] = 'zt_product'; - return $userFields; - } - - // 默认返回空数组 - return array(); + $result = $this->instance->getFieldsWithTable($sql); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -725,69 +298,9 @@ class biModelTest extends baseTest */ public function getFieldsWithAliasTest($sql) { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->instance === null) - { - return $this->mockGetFieldsWithAlias($sql); - } - - try - { - $result = $this->instance->getFieldsWithAlias($sql); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - return $this->mockGetFieldsWithAlias($sql); - } - } - - /** - * Mock getFieldsWithAlias method for testing. - * - * @param string $sql - * @access private - * @return array - */ - private function mockGetFieldsWithAlias($sql) - { - // 处理无效SQL - if(empty($sql) || strpos(strtoupper(trim($sql)), 'SELECT') !== 0) - { - return array(); - } - - // 解析不同类型的SQL语句 - $sql = trim($sql); - - // 处理: SELECT id, account, realname FROM zt_user - if(preg_match('/SELECT\s+id,\s*account,\s*realname\s+FROM\s+zt_user$/i', $sql)) - { - return array('id' => 'id', 'account' => 'account', 'realname' => 'realname'); - } - - // 处理: SELECT id AS user_id, account AS username FROM zt_user - if(preg_match('/SELECT\s+id\s+AS\s+user_id,\s*account\s+AS\s+username\s+FROM\s+zt_user$/i', $sql)) - { - return array('user_id' => 'id', 'username' => 'account'); - } - - // 处理: SELECT u.id, u.account, u.realname FROM zt_user u - if(preg_match('/SELECT\s+u\.id,\s*u\.account,\s*u\.realname\s+FROM\s+zt_user\s+u$/i', $sql)) - { - return array('id' => 'id', 'account' => 'account', 'realname' => 'realname'); - } - - // 处理: SELECT u.account, p.name FROM zt_user u LEFT JOIN zt_product p ON u.id = p.id - if(preg_match('/SELECT\s+u\.account,\s*p\.name\s+FROM\s+zt_user\s+u\s+LEFT\s+JOIN\s+zt_product\s+p/i', $sql)) - { - return array('account' => 'account', 'name' => 'name'); - } - - // 默认返回空数组 - return array(); + $result = $this->instance->getFieldsWithAlias($sql); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -800,46 +313,9 @@ class biModelTest extends baseTest */ public function getTableByAliasTest($statement, $alias) { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->instance === null) - { - return $this->mockGetTableByAlias($statement, $alias); - } - - try - { - $result = $this->instance->getTableByAlias($statement, $alias); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟getTableByAlias方法的行为 - return $this->mockGetTableByAlias($statement, $alias); - } - } - - /** - * Mock getTableByAlias method for testing. - * - * @param mixed $statement - * @param string $alias - * @access private - * @return mixed - */ - private function mockGetTableByAlias($statement, $alias) - { - $table = false; - if($statement->from) - { - foreach($statement->from as $fromInfo) if($fromInfo->alias == $alias) $table = $fromInfo->table; - } - if($statement->join) - { - foreach($statement->join as $joinInfo) if($joinInfo->expr->alias == $alias) $table = $joinInfo->expr->table; - } - return $table; + $result = $this->instance->getTableByAlias($statement, $alias); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -854,7 +330,6 @@ class biModelTest extends baseTest { $result = $this->instance->explainSQL($sql, $driver); if(dao::isError()) return dao::getError(); - return $result; } @@ -869,65 +344,9 @@ class biModelTest extends baseTest */ public function getColumnsTypeTest($sql, $driverName = 'mysql', $columns = array()) { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->instance === null) - { - return $this->mockGetColumnsType($sql, $driverName, $columns); - } - - try - { - $result = $this->instance->getColumnsType($sql, $driverName, $columns); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - return $this->mockGetColumnsType($sql, $driverName, $columns); - } - } - - /** - * Mock getColumnsType method for testing. - * - * @param string $sql - * @param string $driverName - * @param array $columns - * @access private - * @return object - */ - private function mockGetColumnsType($sql, $driverName = 'mysql', $columns = array()) - { - $columnTypes = new stdclass(); - - // 根据SQL语句中的字段名推断字段类型 - if(stripos($sql, 'id') !== false) - { - $columnTypes->id = 'number'; - } - - if(stripos($sql, 'account') !== false) - { - $columnTypes->account = 'string'; - } - - if(stripos($sql, 'realname') !== false) - { - $columnTypes->realname = 'string'; - } - - if(stripos($sql, 'role') !== false) - { - $columnTypes->role = 'string'; - } - - if(stripos($sql, 'total') !== false || stripos($sql, 'count(') !== false) - { - $columnTypes->total = 'string'; - } - - return $columnTypes; + $result = $this->instance->getColumnsType($sql, $driverName, $columns); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -939,86 +358,9 @@ class biModelTest extends baseTest */ public function getScopeOptionsTest($type) { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->instance === null) - { - return $this->mockGetScopeOptions($type); - } - - try - { - $result = $this->instance->getScopeOptions($type); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟getScopeOptions方法的行为 - return $this->mockGetScopeOptions($type); - } - } - - /** - * Mock getScopeOptions method for testing. - * - * @param string $type - * @access private - * @return array - */ - private function mockGetScopeOptions($type) - { - $options = array(); - switch($type) - { - case 'user': - $options = array( - 'admin' => '管理员', - 'user1' => '用户1', - 'user2' => '用户2', - 'user3' => '用户3', - 'user4' => '用户4' - ); - break; - case 'product': - $options = array( - '1' => '产品1', - '2' => '产品2', - '3' => '产品3' - ); - break; - case 'project': - // 模拟无项目或空项目情况 - $options = array(); - break; - case 'execution': - $options = array( - '11' => '执行1', - '12' => '执行2', - '13' => '执行3' - ); - break; - case 'dept': - $options = array( - '1' => '/部门1', - '2' => '/部门2', - '3' => '/部门3' - ); - break; - case 'user.status': - // 模拟语言包数据 - $options = array( - 'active' => '正常', - 'deleted' => '已删除', - 'forbidden' => '禁用' - ); - break; - default: - $options = array(); - break; - } - - return $options; + $result = $this->instance->getScopeOptions($type); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -1033,7 +375,6 @@ class biModelTest extends baseTest { $result = $this->instance->getDataviewOptions($object, $field); if(dao::isError()) return dao::getError(); - return $result; } @@ -1047,89 +388,9 @@ class biModelTest extends baseTest */ public function getObjectOptionsTest($object, $field) { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->instance === null) - { - return $this->mockGetObjectOptions($object, $field); - } - - try - { - $result = $this->instance->getObjectOptions($object, $field); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟getObjectOptions方法的行为 - return $this->mockGetObjectOptions($object, $field); - } - } - - /** - * Mock getObjectOptions method for testing. - * - * @param string $object - * @param string $field - * @access private - * @return array - */ - private function mockGetObjectOptions($object, $field) - { - // 处理空参数 - if(empty($object) || empty($field)) return array(); - - // 模拟objectTables配置 - $objectTables = array( - 'user' => 'zt_user', - 'product' => 'zt_product', - 'project' => 'zt_project', - 'story' => 'zt_story', - 'task' => 'zt_task', - 'bug' => 'zt_bug' - ); - - // 不存在的对象类型返回空数组 - if(!isset($objectTables[$object])) return array(); - - $tableName = $objectTables[$object]; - - // 模拟数据库字段 - $tableFields = array( - 'zt_user' => array('id', 'account', 'realname', 'role', 'email'), - 'zt_product' => array('id', 'name', 'code', 'status', 'desc'), - 'zt_project' => array('id', 'name', 'code', 'status', 'desc'), - 'zt_story' => array('id', 'title', 'type', 'status', 'stage'), - 'zt_task' => array('id', 'name', 'type', 'status', 'pri'), - 'zt_bug' => array('id', 'title', 'type', 'status', 'severity') - ); - - $fields = isset($tableFields[$tableName]) ? $tableFields[$tableName] : array('id'); - - // 不存在的字段时使用id字段 - $useField = in_array($field, $fields) ? $field : 'id'; - - // 模拟查询结果 - switch($object) - { - case 'user': - if($useField == 'id') return array('1' => '1', '2' => '2', '3' => '3'); - if($useField == 'account') return array('1' => 'admin', '2' => 'testuser1', '3' => 'testuser2'); - if($useField == 'realname') return array('1' => '管理员', '2' => '测试用户1', '3' => '测试用户2'); - break; - - case 'product': - if($useField == 'id') return array('1' => '1', '2' => '2'); - if($useField == 'name') return array('1' => '正常产品', '2' => '产品2'); - if($useField == 'code') return array('1' => 'product1', '2' => 'product2'); - break; - - default: - return array('1' => '1', '2' => '2'); - } - - return array(); + $result = $this->instance->getObjectOptions($object, $field); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -1146,7 +407,6 @@ class biModelTest extends baseTest { $result = $this->instance->getOptionsFromSql($sql, $driver, $keyField, $valueField); if(dao::isError()) return dao::getError(); - return $result; } @@ -1162,113 +422,9 @@ class biModelTest extends baseTest */ public function genWaterpoloTest($fields, $settings, $sql, $filters) { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->instance === null) - { - return $this->mockGenWaterpolo($fields, $settings, $sql, $filters); - } - - try - { - $result = $this->instance->genWaterpolo($fields, $settings, $sql, $filters); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟genWaterpolo方法的行为 - return $this->mockGenWaterpolo($fields, $settings, $sql, $filters); - } - } - - /** - * Mock genWaterpolo method for testing. - * - * @param array $fields - * @param array $settings - * @param string $sql - * @param array $filters - * @access private - * @return array - */ - private function mockGenWaterpolo($fields, $settings, $sql, $filters) - { - // 模拟chart配置 - $conditionList = array('eq' => '='); - - $operate = "{$settings['calc']}({$settings['goal']})"; - $sql = "select $operate as count from ($sql) tt "; - - $moleculeSQL = $sql; - $denominatorSQL = $sql; - - $moleculeWheres = array(); - $denominatorWheres = array(); - - foreach($settings['conditions'] as $condition) - { - $where = "{$condition['field']} {$conditionList[$condition['condition']]} '{$condition['value']}'"; - $moleculeWheres[] = $where; - } - - if(!empty($filters)) - { - $wheres = array(); - foreach($filters as $field => $filter) - { - $wheres[] = "$field {$filter['operator']} {$filter['value']}"; - } - $moleculeWheres = array_merge($moleculeWheres, $wheres); - $denominatorWheres = $wheres; - } - - if($moleculeWheres) $moleculeSQL .= 'where ' . implode(' and ', $moleculeWheres); - if($denominatorWheres) $denominatorSQL .= 'where ' . implode(' and ', $denominatorWheres); - - // 模拟查询结果 - $moleculeCount = 0; - $denominatorCount = 0; - - // 根据条件模拟不同的计数结果 - if(empty($settings['conditions'])) - { - // 空条件,模拟查询所有记录 - $moleculeCount = 10; - $denominatorCount = 10; - } - elseif($settings['conditions'][0]['value'] == '999') - { - // 分母为零的测试场景 - $moleculeCount = 0; - $denominatorCount = 0; - } - elseif($settings['conditions'][0]['value'] == '0') - { - // 正常情况,非删除用户 - $moleculeCount = 8; - $denominatorCount = 10; - } - else - { - // 其他情况 - $moleculeCount = 5; - $denominatorCount = 10; - } - - // 如果有过滤器,调整计数 - if(!empty($filters)) - { - $denominatorCount = $moleculeCount; // 分母受过滤器影响 - } - - $percent = $denominatorCount ? round((int)$moleculeCount / (int)$denominatorCount, 4) : 0; - - $series = array(array('type' => 'liquidFill', 'data' => array($percent), 'color' => array('#2e7fff'), 'outline' => array('show' => false), 'label' => array('fontSize' => 26))); - $tooltip = array('show' => true); - $options = array('series' => $series, 'tooltip' => $tooltip); - - return $options; + $result = $this->instance->genWaterpolo($fields, $settings, $sql, $filters); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -1286,7 +442,6 @@ class biModelTest extends baseTest { $result = $this->instance->getMultiData($settings, $defaultSql, $filters, $driver, $sort); if(dao::isError()) return dao::getError(); - return $result; } @@ -1298,107 +453,9 @@ class biModelTest extends baseTest */ public function getTableFieldsTest() { - // 如果model未初始化(数据库连接失败),返回mock数据用于测试 - if($this->instance === null) - { - return 'array'; - } - $result = $this->instance->getTableFields(); if(dao::isError()) return dao::getError(); - - return is_array($result) ? 'array' : 'not_array'; - } - - /** - * Test getTableFields method returns not empty. - * - * @access public - * @return string - */ - public function getTableFieldsTestNotEmpty() - { - if($this->instance === null) return 'not_empty'; - - $result = $this->instance->getTableFields(); - if(dao::isError()) return dao::getError(); - - return !empty($result) ? 'not_empty' : 'empty'; - } - - /** - * Test getTableFields method has tables. - * - * @access public - * @return string - */ - public function getTableFieldsTestHasTables() - { - if($this->instance === null) return 'has_tables'; - - $result = $this->instance->getTableFields(); - if(dao::isError()) return dao::getError(); - - if(!is_array($result) || empty($result)) return 'no_tables'; - - foreach($result as $table => $fields) - { - if(strpos($table, 'zt_') === 0) return 'has_tables'; - } - - return 'no_tables'; - } - - /** - * Test getTableFields method has fields for each table. - * - * @access public - * @return string - */ - public function getTableFieldsTestHasFields() - { - if($this->instance === null) return 'has_fields'; - - $result = $this->instance->getTableFields(); - if(dao::isError()) return dao::getError(); - - if(!is_array($result) || empty($result)) return 'no_fields'; - - foreach($result as $table => $fields) - { - if(!is_array($fields) || empty($fields)) return 'no_fields'; - } - - return 'has_fields'; - } - - /** - * Test getTableFields method has valid structure. - * - * @access public - * @return string - */ - public function getTableFieldsTestValidStructure() - { - if($this->instance === null) return 'valid_structure'; - - $result = $this->instance->getTableFields(); - if(dao::isError()) return dao::getError(); - - if(!is_array($result) || empty($result)) return 'invalid_structure'; - - foreach($result as $table => $fields) - { - if(!is_array($fields)) return 'invalid_structure'; - - foreach($fields as $fieldName => $fieldInfo) - { - if(!is_array($fieldInfo)) return 'invalid_structure'; - if(!isset($fieldInfo['type'])) return 'invalid_structure'; - } - } - - return 'valid_structure'; + return $result; } /** @@ -1409,302 +466,9 @@ class biModelTest extends baseTest */ public function getTableFieldsMenuTest() { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->instance === null) - { - return $this->mockGetTableFieldsMenu(); - } - - try - { - $result = $this->instance->getTableFieldsMenu(); - if(dao::isError()) return dao::getError(); - - // 为了测试断言,返回类型标识 - if(is_array($result) && !empty($result)) - { - return 'array'; - } - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,使用mock方式 - return $this->mockGetTableFieldsMenu(); - } - } - - /** - * Mock getTableFieldsMenu method for testing. - * - * @access private - * @return string - */ - private function mockGetTableFieldsMenu() - { - // 模拟getTableFields返回的数据结构 - $tableFields = array( - 'zt_user' => array( - 'id' => array('type' => 'int'), - 'account' => array('type' => 'varchar'), - 'realname' => array('type' => 'varchar') - ), - 'zt_product' => array( - 'id' => array('type' => 'int'), - 'name' => array('type' => 'varchar'), - 'status' => array('type' => 'varchar') - ), - 'zt_project' => array( - 'id' => array('type' => 'int'), - 'name' => array('type' => 'varchar'), - 'status' => array('type' => 'varchar') - ) - ); - - // 模拟getTableFieldsMenu的逻辑 - $menu = array(); - foreach($tableFields as $table => $fields) - { - $tableItem = array(); - $tableItem['key'] = $table; - $tableItem['text'] = $table . '(table)'; - $tableItem['items'] = array(); - - foreach($fields as $field => $fieldInfo) - { - $fieldItem = array(); - $fieldItem['key'] = $field; - $fieldItem['text'] = $field . '(' . $fieldInfo['type'] . ')'; - - $tableItem['items'][] = $fieldItem; - } - - $menu[] = $tableItem; - } - - // 为了测试断言,返回类型标识 - if(is_array($menu) && !empty($menu)) - { - return 'array'; - } - - return $menu; - } - - /** - * Test getTableFieldsMenu method for empty case. - * - * @access public - * @return mixed - */ - public function getTableFieldsMenuTestEmpty() - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->instance === null) - { - return $this->mockGetTableFieldsMenuEmpty(); - } - - try - { - // 模拟获取空的表字段情况 - $result = $this->instance->getTableFieldsMenu(); - if(dao::isError()) return dao::getError(); - - if(is_array($result) && empty($result)) - { - return 'empty'; - } - - // 如果有数据,返回非空标识(正常情况) - return 'not_empty'; - } - catch(Exception $e) - { - // 当数据库连接失败时,使用mock方式 - return $this->mockGetTableFieldsMenuEmpty(); - } - } - - /** - * Mock getTableFieldsMenu method for empty case testing. - * - * @access private - * @return string - */ - private function mockGetTableFieldsMenuEmpty() - { - // 正常情况下应该有数据,所以返回not_empty - return 'not_empty'; - } - - /** - * Test getTableFieldsMenu method structure validation. - * - * @access public - * @return mixed - */ - public function getTableFieldsMenuTestStructure() - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->instance === null) - { - return $this->mockGetTableFieldsMenuStructure(); - } - - try - { - $result = $this->instance->getTableFieldsMenu(); - if(dao::isError()) return dao::getError(); - - if(!is_array($result)) return 'invalid_type'; - if(empty($result)) return 'empty'; - - $firstItem = reset($result); - if(!is_array($firstItem)) return 'invalid_structure'; - - // 检查必要的属性 - if(!isset($firstItem['key'])) return 'no_key'; - if(!isset($firstItem['text'])) return 'no_text'; - if(!isset($firstItem['items'])) return 'no_items'; - - return 'valid'; - } - catch(Exception $e) - { - // 当数据库连接失败时,使用mock方式 - return $this->mockGetTableFieldsMenuStructure(); - } - } - - /** - * Mock getTableFieldsMenu method for structure testing. - * - * @access private - * @return string - */ - private function mockGetTableFieldsMenuStructure() - { - // 模拟正确的结构并直接返回valid - return 'valid'; - } - - /** - * Test getTableFieldsMenu method format validation. - * - * @access public - * @return mixed - */ - public function getTableFieldsMenuTestFormat() - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->instance === null) - { - return $this->mockGetTableFieldsMenuFormat(); - } - - try - { - $result = $this->instance->getTableFieldsMenu(); - if(dao::isError()) return dao::getError(); - - if(!is_array($result) || empty($result)) return 'invalid'; - - $firstItem = reset($result); - - // 检查text格式是否包含(table)后缀 - if(!strpos($firstItem['text'], '(table)')) return 'invalid_table_format'; - - // 检查items中的字段格式 - if(!empty($firstItem['items'])) - { - $firstField = reset($firstItem['items']); - if(!strpos($firstField['text'], '(') || !strpos($firstField['text'], ')')) - { - return 'invalid_field_format'; - } - } - - return 'valid'; - } - catch(Exception $e) - { - // 当数据库连接失败时,使用mock方式 - return $this->mockGetTableFieldsMenuFormat(); - } - } - - /** - * Mock getTableFieldsMenu method for format testing. - * - * @access private - * @return string - */ - private function mockGetTableFieldsMenuFormat() - { - // 模拟正确的格式并直接返回valid - return 'valid'; - } - - /** - * Test getTableFieldsMenu method hierarchy validation. - * - * @access public - * @return mixed - */ - public function getTableFieldsMenuTestHierarchy() - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->instance === null) - { - return $this->mockGetTableFieldsMenuHierarchy(); - } - - try - { - $result = $this->instance->getTableFieldsMenu(); - if(dao::isError()) return dao::getError(); - - if(!is_array($result) || empty($result)) return 'invalid'; - - $firstItem = reset($result); - - // 检查二级结构 - if(!isset($firstItem['items']) || !is_array($firstItem['items'])) - { - return 'no_hierarchy'; - } - - // 检查items中的项目结构 - if(!empty($firstItem['items'])) - { - $firstField = reset($firstItem['items']); - if(!isset($firstField['key']) || !isset($firstField['text'])) - { - return 'invalid_field_structure'; - } - } - - return 'valid'; - } - catch(Exception $e) - { - // 当数据库连接失败时,使用mock方式 - return $this->mockGetTableFieldsMenuHierarchy(); - } - } - - /** - * Mock getTableFieldsMenu method for hierarchy testing. - * - * @access private - * @return string - */ - private function mockGetTableFieldsMenuHierarchy() - { - // 模拟正确的层级结构并直接返回valid - return 'valid'; + $result = $this->instance->getTableFieldsMenu(); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -1718,7 +482,6 @@ class biModelTest extends baseTest { $result = $this->instance->preparePivotObject($pivot); if(dao::isError()) return dao::getError(); - return $result; } @@ -1735,7 +498,6 @@ class biModelTest extends baseTest { $result = $this->instance->prepareBuilitinPivotDrillSQL($pivotID, $drills, $version); if(dao::isError()) return dao::getError(); - return $result; } @@ -1750,7 +512,6 @@ class biModelTest extends baseTest { $result = $this->instance->prepareBuiltinMetricSQL($operate); if(dao::isError()) return dao::getError(); - return $result; } @@ -1765,40 +526,6 @@ class biModelTest extends baseTest { $result = $this->instance->prepareBuiltinScreenSQL($operate); if(dao::isError()) return dao::getError(); - - // 如果是数组且不为空,返回'array'用于测试 - if(is_array($result) && !empty($result)) - { - return 'array'; - } - - // 如果是空数组,返回'empty' - if(is_array($result) && empty($result)) - { - return 'empty'; - } - - return $result; - } - - /** - * Test prepareBuiltinScreenSQL method for SQL content validation. - * - * @param string $operate - * @access public - * @return mixed - */ - public function prepareBuiltinScreenSQLContentTest($operate = 'insert') - { - $result = $this->instance->prepareBuiltinScreenSQL($operate); - if(dao::isError()) return dao::getError(); - - if(!is_array($result) || empty($result)) - { - return array(); - } - - // 返回SQL数组用于内容检查 return $result; } @@ -1812,7 +539,6 @@ class biModelTest extends baseTest { $result = $this->instance->getDuckDBPath(); if(dao::isError()) return dao::getError(); - return $result; } @@ -1826,23 +552,9 @@ class biModelTest extends baseTest */ public function checkDuckDBFileTest($path, $bin) { - try { - // 验证必要的参数键是否存在 - if(!isset($bin['file']) || !isset($bin['extension'])) { - return false; - } - - // 调用模型方法 - $result = $this->instance->checkDuckDBFile($path, $bin); - if(dao::isError()) return dao::getError(); - - // 如果返回对象,返回'object'用于断言 - if(is_object($result)) return 'object'; - - return $result; - } catch (Exception $e) { - return false; - } + $result = $this->instance->checkDuckDBFile($path, $bin); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -1855,7 +567,6 @@ class biModelTest extends baseTest { $result = $this->instance->getDuckdbBinConfig(); if(dao::isError()) return dao::getError(); - return $result; } @@ -1870,7 +581,6 @@ class biModelTest extends baseTest { $result = $this->instance->getDuckDBTmpDir($static); if(dao::isError()) return dao::getError(); - return $result; } @@ -1886,7 +596,6 @@ class biModelTest extends baseTest { $result = $this->instance->getSqlByMonth($year, $month); if(dao::isError()) return dao::getError(); - return $result; } @@ -1901,7 +610,6 @@ class biModelTest extends baseTest { $result = $this->instance->getActionSyncSql($range); if(dao::isError()) return dao::getError(); - return $result; } @@ -1915,7 +623,6 @@ class biModelTest extends baseTest { $result = $this->instance->initParquet(); if(dao::isError()) return dao::getError(); - return $result; } @@ -1930,7 +637,6 @@ class biModelTest extends baseTest { $result = $this->instance->prepareCopySQL($duckdbTmpPath); if(dao::isError()) return dao::getError(); - return $result; } @@ -1947,7 +653,6 @@ class biModelTest extends baseTest { $result = $this->instance->prepareSyncCommand($binPath, $extensionPath, $copySQL); if(dao::isError()) return dao::getError(); - return $result; } @@ -1961,7 +666,6 @@ class biModelTest extends baseTest { $result = $this->instance->generateParquetFile(); if(dao::isError()) return dao::getError(); - return $result; } @@ -1975,49 +679,9 @@ class biModelTest extends baseTest { $result = $this->instance->getLogFile(); if(dao::isError()) return dao::getError(); - return $result; } - /** - * Test saveLogs method. - * - * @param string $log - * @access public - * @return mixed - */ - public function saveLogsTest($log) - { - $tmpDir = sys_get_temp_dir() . DIRECTORY_SEPARATOR; - $logFile = $tmpDir . 'test_saveLogs_' . date('Ymd') . '.log.php'; - - // 删除现有日志文件以确保测试环境干净 - if(file_exists($logFile)) unlink($logFile); - - // 模拟 saveLogs 方法的逻辑 - $logContent = date('Y-m-d H:i:s') . ' ' . trim($log) . "\n"; - if(!file_exists($logFile)) $logContent = "\n" . $logContent; - - file_put_contents($logFile, $logContent, FILE_APPEND); - - // 检查文件是否被创建 - if(!file_exists($logFile)) return false; - - // 读取文件内容进行验证 - $content = file_get_contents($logFile); - - // 清理测试文件 - if(file_exists($logFile)) unlink($logFile); - - return array( - 'fileExists' => true, - 'hasPhpHeader' => strpos($content, ' strpos($content, 'die();') !== false, - 'hasLogContent' => strpos($content, $log) !== false, - 'hasTimestamp' => preg_match('/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', $content) === 1 - ); - } - /** * Test parseSqlVars method. * @@ -2030,7 +694,6 @@ class biModelTest extends baseTest { $result = $this->instance->parseSqlVars($sql, $filters); if(dao::isError()) return dao::getError(); - return $result; } @@ -2044,30 +707,9 @@ class biModelTest extends baseTest */ public function sql2StatementTest($sql, $mode = 'text') { - // Mock sql2Statement method behavior - // 简化的SQL解析逻辑 - $sql = trim($sql); - - // 空SQL处理 - if(empty($sql)) - { - if($mode == 'builder') return '请正确配置构建器'; - return '请输入一条正确的SQL语句'; - } - - // 检查多条语句 - if(substr_count($sql, ';') > 1 || (substr_count($sql, ';') == 1 && !preg_match('/;\s*$/', $sql))) - { - return '只能输入一条SQL语句'; - } - - // 检查是否为SELECT语句 - if(!preg_match('/^\s*select\s+/i', $sql)) - { - return '只允许SELECT查询'; - } - - return 'object'; + $result = $this->instance->sql2Statement($sql, $mode); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -2080,29 +722,9 @@ class biModelTest extends baseTest */ public function validateSqlTest($sql, $driver = 'mysql') { - // 模拟validateSql方法的行为,避免实际数据库操作 - if(empty($sql)) return '请输入一条正确的SQL语句'; - - // 对于简单的有效SQL,直接返回true - if(strpos(strtoupper(trim($sql)), 'SELECT') === 0) - { - // 检查是否有重复字段 - 简单检测 - if(preg_match('/SELECT\s+.*\s+as\s+(\w+).*\s+as\s+\1/i', $sql, $matches)) - { - return "存在重复的字段名: " . $matches[1] . "。建议您:(1)修改 * 查询为具体的字段。(2)使用 as 为字段设置别名。"; - } - - // 检查是否包含不存在的表 - if(strpos($sql, 'zt_nonexistent_table') !== false) - { - return "Table 'zttest.zt_nonexistent_table' doesn't exist"; - } - - return true; - } - - // 非SELECT语句返回语法错误 - return "You have an error in your SQL syntax"; + $result = $this->instance->validateSql($sql, $driver); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -2119,7 +741,6 @@ class biModelTest extends baseTest { $result = $this->instance->prepareSqlPager($statement, $recPerPage, $pageID, $driver); if(dao::isError()) return dao::getError(); - return $result; } @@ -2134,22 +755,9 @@ class biModelTest extends baseTest */ public function prepareColumnsTest($sql, $statement, $driver = 'mysql') { - if($this->instance === null) - { - return $this->mockPrepareColumns($sql, $statement, $driver); - } - - try - { - $result = $this->instance->prepareColumns($sql, $statement, $driver); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - return $this->mockPrepareColumns($sql, $statement, $driver); - } + $result = $this->instance->prepareColumns($sql, $statement, $driver); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -2162,79 +770,9 @@ class biModelTest extends baseTest */ public function getSqlTypeAndFieldsTest($sql, $driver = 'mysql') { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->instance === null) - { - return $this->mockGetSqlTypeAndFields($sql, $driver); - } - - try - { - $result = $this->instance->getSqlTypeAndFields($sql, $driver); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - return $this->mockGetSqlTypeAndFields($sql, $driver); - } - } - - /** - * Mock getSqlTypeAndFields method for testing. - * - * @param string $sql - * @param string $driver - * @access private - * @return array - */ - private function mockGetSqlTypeAndFields($sql, $driver = 'mysql') - { - // 根据SQL语句分析字段类型 - $columnTypes = new stdclass(); - $columnFields = array(); - - // 处理 SELECT id, account FROM zt_user 类型的SQL - if(preg_match('/SELECT\s+(.+?)\s+FROM\s+/i', $sql, $matches)) - { - $fields = explode(',', $matches[1]); - foreach($fields as $field) - { - $field = trim($field); - - // 移除表别名前缀(如 u.id -> id) - if(strpos($field, '.') !== false) - { - $field = substr($field, strpos($field, '.') + 1); - } - - // 根据字段名推断类型 - if($field == 'id') - { - $columnTypes->id = 'number'; - $columnFields['id'] = 'id'; - } - elseif($field == 'account') - { - $columnTypes->account = 'string'; - $columnFields['account'] = 'account'; - } - elseif(in_array($field, array('realname', 'name', 'title', 'desc'))) - { - $columnTypes->$field = 'string'; - $columnFields[$field] = $field; - } - else - { - // 默认为字符串类型 - $columnTypes->$field = 'string'; - $columnFields[$field] = $field; - } - } - } - - return array($columnTypes, $columnFields); + $result = $this->instance->getSqlTypeAndFields($sql, $driver); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -2248,59 +786,9 @@ class biModelTest extends baseTest */ public function getParams4RebuildTest($sql, $statement, $columnFields) { - // Mock返回值来测试方法的基本逻辑,避免数据库依赖 - $tableAndFields = array('tables' => array(), 'fields' => array()); - - // 模拟getTableAndFields的结果 - if($statement && $statement->expr) - { - $fields = array(); - foreach($statement->expr as $expr) - { - $field = $expr->expr; - $alias = $field; - if(!empty($expr->alias)) - { - $alias = $expr->alias; - } - elseif(strrpos($field, '.') !== false) - { - $alias = explode('.', $field)[1]; - } - $fields[$alias] = $field; - } - $tableAndFields['fields'] = $fields; - } - - $moduleNames = array(); - $aliasNames = array(); - $fieldPairs = array(); - $relatedObjects = array(); - - // 模拟dataview->mergeFields的简单实现 - foreach($columnFields as $field => $value) - { - $fieldPairs[$field] = $value; - $relatedObjects[$field] = ''; - } - - // 如果字段列表为空,使用SQL解析的字段 - if(empty($fieldPairs) && !empty($tableAndFields['fields'])) - { - foreach($tableAndFields['fields'] as $alias => $field) - { - $fieldPairs[$alias] = $alias; - $relatedObjects[$alias] = ''; - } - } - - // 应用字符过滤逻辑,与原方法保持一致 - foreach($fieldPairs as $field => $name) - { - $fieldPairs[$field] = preg_replace('/[^\x{4e00}-\x{9fa5}0-9a-zA-Z_]/u', '', $name); - } - - return array($moduleNames, $aliasNames, $fieldPairs, $relatedObjects); + $result = $this->instance->getParams4Rebuild($sql, $statement, $columnFields); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -2315,47 +803,9 @@ class biModelTest extends baseTest */ public function getSQLTest($sql, $driver = 'mysql', $recPerPage = 10, $pageID = 1) { - // 直接模拟getSQL方法的核心逻辑,避免复杂的依赖 - try - { - // 模拟sql2Statement的行为 - 创建一个基础的statement对象 - $statement = new stdclass(); - $statement->limit = null; - $statement->options = new stdclass(); - $statement->options->options = array(); - - // 模拟prepareSqlPager的逻辑 - if(!$statement->limit) - { - $statement->limit = new stdclass(); - } - $statement->limit->offset = $recPerPage * ($pageID - 1); - $statement->limit->rowCount = $recPerPage; - - if($driver == 'mysql') $statement->options->options[] = 'SQL_CALC_FOUND_ROWS'; - - // 模拟build()方法的返回值 - $offset = $recPerPage * ($pageID - 1); - $limitSql = $driver == 'mysql' - ? "SELECT SQL_CALC_FOUND_ROWS * FROM ($sql) LIMIT $offset, $recPerPage" - : "$sql LIMIT $offset, $recPerPage"; - - // 根据驱动类型生成countSql - $countSql = "SELECT FOUND_ROWS() AS count"; - if($driver == 'duckdb') $countSql = "SELECT COUNT(1) AS count FROM ($sql)"; - if($driver == 'dm') $countSql = "SELECT COUNT(1) as count FROM ($sql)"; - - $result = array($limitSql, $countSql); - - // 确保结果是一个数组,包含两个元素 - if(!is_array($result) || count($result) != 2) return 0; - - return count($result); - } - catch(Exception $e) - { - return 0; - } + $result = $this->instance->getSQL($sql, $driver, $recPerPage, $pageID); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -2369,17 +819,9 @@ class biModelTest extends baseTest */ public function querySQLTest($sql, $limitSql, $driver = 'mysql') { - try - { - $result = $this->instance->querySQL($sql, $limitSql, $driver); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - return array('result' => 'fail', 'message' => $e->getMessage()); - } + $result = $this->instance->querySQL($sql, $limitSql, $driver); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -2393,57 +835,9 @@ class biModelTest extends baseTest */ public function queryTest($sqlOrStateObj, $driver = 'mysql', $useFilter = true) { - // 直接模拟query方法的基本验证逻辑,避免实际数据库操作 - if(is_string($sqlOrStateObj)) - { - $sql = $sqlOrStateObj; - } - else if(is_object($sqlOrStateObj) && isset($sqlOrStateObj->sql)) - { - $sql = $sqlOrStateObj->sql; - } - else - { - return 1; // 无效参数 - } - - // 空SQL检测 - if(empty($sql)) return 1; - - // SQL语法基本检测 - $sql = trim($sql); - $sqlUpper = strtoupper($sql); - - // 检查是否为SELECT语句 - if(strpos($sqlUpper, 'SELECT') !== 0) return 1; - - // 检查无效关键字 - if(strpos($sqlUpper, 'INVALID') !== false) return 1; - if(strpos($sqlUpper, 'INSERT') !== false) return 1; - if(strpos($sqlUpper, 'UPDATE') !== false) return 1; - if(strpos($sqlUpper, 'DELETE') !== false) return 1; - - // 对于某些驱动的特殊处理 - if($driver == 'duckdb') - { - // DuckDB驱动下简单SQL应该能正常工作 - return 0; - } - - // 基本的有效SQL检测 - if($sqlUpper == 'SELECT 1 AS TEST_COL' || - $sqlUpper == 'SELECT COUNT(*) AS TOTAL FROM ZT_USER') - { - return 0; - } - - // 其他有效的SELECT语句 - if(preg_match('/^SELECT\s+.+/', $sqlUpper)) - { - return 0; - } - - return 1; + $result = $this->instance->query($sqlOrStateObj, $driver, $useFilter); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -2456,26 +850,9 @@ class biModelTest extends baseTest */ public function getTableListTest($hasDataview = true, $withPrefix = true) { - // Due to database initialization issues in test environment, - // we provide a mock implementation that simulates the expected behavior - $tableList = array(); - - // Mock original tables with proper prefix - $prefix = $withPrefix ? 'zt_' : ''; - $tableList[$prefix . 'user'] = '用户'; - $tableList[$prefix . 'product'] = '产品'; - $tableList[$prefix . 'project'] = '项目'; - $tableList[$prefix . 'story'] = '需求'; - $tableList[$prefix . 'task'] = '任务'; - - // Mock dataview tables if requested - if($hasDataview) { - $dataviewPrefix = $withPrefix ? 'ztv_' : ''; - $tableList[$dataviewPrefix . 'user_view'] = '用户视图'; - $tableList[$dataviewPrefix . 'product_view'] = '产品视图'; - } - - return $tableList; + $result = $this->instance->getTableList($hasDataview, $withPrefix); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -2486,75 +863,9 @@ class biModelTest extends baseTest */ public function prepareFieldObjectsTest() { - try - { - /* Enhanced mock data to ensure comprehensive test coverage */ - $mockResult = array( - array('text' => '产品', 'value' => 'product', 'fields' => array()), - array('text' => '软件需求', 'value' => 'story', 'fields' => array()), - array('text' => '版本', 'value' => 'build', 'fields' => array()), - array('text' => '产品计划', 'value' => 'productplan', 'fields' => array()), - array('text' => '发布', 'value' => 'release', 'fields' => array()), - array('text' => 'Bug', 'value' => 'bug', 'fields' => array()), - array('text' => '项目', 'value' => 'project', 'fields' => array()), - array('text' => '任务', 'value' => 'task', 'fields' => array()), - ); - - /* Try to call the actual method, fall back to mock if it fails */ - try { - $result = $this->instance->prepareFieldObjects(); - if(dao::isError() || empty($result)) return $mockResult; - return $result; - } catch(Exception $e) { - return $mockResult; - } catch(Error $e) { - return $mockResult; - } catch(Throwable $e) { - return $mockResult; - } - } - catch(Exception $e) - { - /* Return mock data instead of throwing exception to avoid test failures */ - return array( - array('text' => '产品', 'value' => 'product', 'fields' => array()), - array('text' => '软件需求', 'value' => 'story', 'fields' => array()), - array('text' => '版本', 'value' => 'build', 'fields' => array()), - array('text' => '产品计划', 'value' => 'productplan', 'fields' => array()), - array('text' => '发布', 'value' => 'release', 'fields' => array()), - array('text' => 'Bug', 'value' => 'bug', 'fields' => array()), - array('text' => '项目', 'value' => 'project', 'fields' => array()), - array('text' => '任务', 'value' => 'task', 'fields' => array()), - ); - } - catch(Error $e) - { - /* Handle fatal errors gracefully with mock data */ - return array( - array('text' => '产品', 'value' => 'product', 'fields' => array()), - array('text' => '软件需求', 'value' => 'story', 'fields' => array()), - array('text' => '版本', 'value' => 'build', 'fields' => array()), - array('text' => '产品计划', 'value' => 'productplan', 'fields' => array()), - array('text' => '发布', 'value' => 'release', 'fields' => array()), - array('text' => 'Bug', 'value' => 'bug', 'fields' => array()), - array('text' => '项目', 'value' => 'project', 'fields' => array()), - array('text' => '任务', 'value' => 'task', 'fields' => array()), - ); - } - catch(Throwable $e) - { - /* Handle any other throwable errors with mock data */ - return array( - array('text' => '产品', 'value' => 'product', 'fields' => array()), - array('text' => '软件需求', 'value' => 'story', 'fields' => array()), - array('text' => '版本', 'value' => 'build', 'fields' => array()), - array('text' => '产品计划', 'value' => 'productplan', 'fields' => array()), - array('text' => '发布', 'value' => 'release', 'fields' => array()), - array('text' => 'Bug', 'value' => 'bug', 'fields' => array()), - array('text' => '项目', 'value' => 'project', 'fields' => array()), - array('text' => '任务', 'value' => 'task', 'fields' => array()), - ); - } + $result = $this->instance->prepareFieldObjects(); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -2568,7 +879,6 @@ class biModelTest extends baseTest { $result = $this->instance->prepareFieldSettingFormData($settings); if(dao::isError()) return dao::getError(); - return $result; } @@ -2587,7 +897,6 @@ class biModelTest extends baseTest { $result = $this->instance->rebuildFieldSettings($fieldPairs, $columns, $relatedObject, $fieldSettings, $objectFields); if(dao::isError()) return dao::getError(); - return $result; } @@ -2603,115 +912,9 @@ class biModelTest extends baseTest */ public function convertDataForDtableTest($data, $configs, $version, $status) { - // 如果模型对象为null(数据库连接失败),直接使用mock模式 - if($this->instance === null) - { - return $this->mockConvertDataForDtable($data, $configs, $version, $status); - } - - try - { - $result = $this->instance->convertDataForDtable($data, $configs, $version, $status); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟convertDataForDtable方法的行为 - return $this->mockConvertDataForDtable($data, $configs, $version, $status); - } - } - - /** - * Mock convertDataForDtable method for testing when database unavailable. - * - * @param object $data - * @param array $configs - * @param string $version - * @param string $status - * @access private - * @return array - */ - private function mockConvertDataForDtable($data, $configs, $version, $status) - { - $columns = array(); - $rows = array(); - $cellSpan = array(); - - $headerRow1 = !empty($data->cols[0]) ? $data->cols[0] : array(); - $headerRow2 = !empty($data->cols[1]) ? $data->cols[1] : array(); - - // 模拟列配置生成 - $index = 0; - foreach($headerRow1 as $column) - { - if(!empty($column->colspan) && $column->isSlice && !empty($headerRow2)) - { - $colspan = 0; - while($colspan < $column->colspan) - { - $subColumn = array_shift($headerRow2); - $field = 'field' . $index; - $columns[$field]['name'] = $field; - $columns[$field]['title'] = empty($subColumn->label) ? ' ' : $subColumn->label; - $columns[$field]['headerGroup'] = $column->label; - - if(isset($subColumn->isDrilling) && $subColumn->isDrilling) - { - $columns[$field]['link'] = '#'; - $columns[$field]['drillField'] = $subColumn->drillField; - $columns[$field]['condition'] = $subColumn->condition; - } - - $colspan += $subColumn->colspan ?: 1; - $index++; - } - continue; - } - - $field = 'field' . $index; - $columns[$field]['name'] = $field; - $columns[$field]['title'] = empty($column->label) ? ' ' : $column->label; - - if(isset($column->isDrilling) && $column->isDrilling) - { - $columns[$field]['link'] = '#'; - $columns[$field]['drillField'] = $column->drillField; - $columns[$field]['condition'] = $column->condition; - } - - $index++; - } - - // 模拟行数据生成 - foreach($data->array as $rowKey => $rowData) - { - $index = 0; - foreach($rowData as $value) - { - $field = 'field' . $index; - $rows[$rowKey][$field] = $value; - - // 处理合并单元格配置 - if(isset($configs[$rowKey][$index]) && $configs[$rowKey][$index] > 1) - { - $rows[$rowKey][$field . '_rowspan'] = $configs[$rowKey][$index]; - $cellSpan[$field]['rowspan'] = $field . '_rowspan'; - } - - $index++; - } - - $rows[$rowKey]['conditions'] = array(); - $rows[$rowKey]['isDrill'] = array(); - $rows[$rowKey]['isTotal'] = false; - $rows[$rowKey]['ROW_ID'] = $rowKey; - $rows[$rowKey]['version'] = $version; - $rows[$rowKey]['status'] = $status; - } - - return array($columns, $rows, $cellSpan); + $result = $this->instance->convertDataForDtable($data, $configs, $version, $status); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -2725,40 +928,9 @@ class biModelTest extends baseTest */ public function getDrillFieldsTest(int $rowIndex, string $columnKey, array $drills): array { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->instance === null) - { - return $this->mockGetDrillFields($rowIndex, $columnKey, $drills); - } - - try - { - $result = $this->instance->getDrillFields($rowIndex, $columnKey, $drills); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟getDrillFields方法的行为 - return $this->mockGetDrillFields($rowIndex, $columnKey, $drills); - } - } - - /** - * Mock getDrillFields method for testing. - * - * @param int $rowIndex - * @param string $columnKey - * @param array $drills - * @access private - * @return array - */ - private function mockGetDrillFields(int $rowIndex, string $columnKey, array $drills): array - { - if(empty($drills) || !isset($drills[$rowIndex]) || !isset($drills[$rowIndex]['drillFields'][$columnKey])) return array(); - - return $drills[$rowIndex]['drillFields'][$columnKey]; + $result = $this->instance->getDrillFields($rowIndex, $columnKey, $drills); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -2774,7 +946,6 @@ class biModelTest extends baseTest { $result = $this->instance->processDrills($field, $drillFields, $columns); if(dao::isError()) return dao::getError(); - return $result; } @@ -2791,7 +962,6 @@ class biModelTest extends baseTest { $result = $this->instance->prepareDrillConditions($drillFields, $conditions, $originField); if(dao::isError()) return dao::getError(); - return $result; } @@ -2804,18 +974,8 @@ class biModelTest extends baseTest */ public function json2ArrayTest($json): array { - // 如果数据库连接失败,直接实现json2Array的逻辑 - if($this->instance === null) - { - if(empty($json)) return array(); - if(is_string($json)) return json_decode($json, true); - if(is_object($json)) return json_decode(json_encode($json), true); - return $json; - } - $result = $this->instance->json2Array($json); if(dao::isError()) return dao::getError(); - return $result; } @@ -2829,93 +989,9 @@ class biModelTest extends baseTest */ public function getCorrectGroupTest($id, $type) { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->instance === null) - { - return $this->mockGetCorrectGroup($id, $type); - } - - try - { - $result = $this->instance->getCorrectGroup($id, $type); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟getCorrectGroup方法的行为 - return $this->mockGetCorrectGroup($id, $type); - } - } - - /** - * Mock getCorrectGroup method for testing. - * - * @param string $id - * @param string $type - * @access private - * @return string - */ - private function mockGetCorrectGroup($id, $type) - { - // 处理多个ID的情况 - if(strpos($id, ',') !== false) - { - $ids = explode(',', $id); - $correctIds = array(); - foreach($ids as $singleId) - { - $correctId = $this->mockGetCorrectGroup($singleId, $type); - if($correctId !== '') $correctIds[] = $correctId; - } - return empty($correctIds) ? '' : implode(',', $correctIds); - } - - // 空字符串直接返回空 - if(empty($id)) return ''; - - // 模拟配置数据 - $charts = array( - '32' => array("root" => 1, "name" => "产品", "grade" => 1), - '33' => array("root" => 1, "name" => "项目", "grade" => 1), - '34' => array("root" => 1, "name" => "测试", "grade" => 1), - '35' => array("root" => 1, "name" => "组织", "grade" => 1), - '36' => array("root" => 1, "name" => "需求", "grade" => 2) - ); - - $pivots = array( - '59' => array("root" => 1, "name" => "产品", "grade" => 1), - '60' => array("root" => 1, "name" => "项目", "grade" => 1), - '61' => array("root" => 1, "name" => "测试", "grade" => 1), - '62' => array("root" => 1, "name" => "组织", "grade" => 1) - ); - - $key = "{$type}s"; - $builtinModules = $type == 'chart' ? $charts : $pivots; - - if(!isset($builtinModules[$id])) return ''; - - $builtinModule = $builtinModules[$id]; - - // 模拟数据库查询结果 - 根据配置模拟对应的数据库ID - $moduleMapping = array( - 'chart' => array( - '32' => '1', // 产品,grade=1 -> id=1 - '33' => '2', // 项目,grade=1 -> id=2 - '34' => '3', // 测试,grade=1 -> id=3 - '35' => '4', // 组织,grade=1 -> id=4 - '36' => '5' // 需求,grade=2 -> id=5 - ), - 'pivot' => array( - '59' => '9', // 产品,grade=1 -> id=9 - '60' => '10', // 项目,grade=1 -> id=10 - '61' => '11', // 测试,grade=1 -> id=11 - '62' => '12' // 组织,grade=1 -> id=12 - ) - ); - - return isset($moduleMapping[$type][$id]) ? $moduleMapping[$type][$id] : ''; + $result = $this->instance->getCorrectGroup($id, $type); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -2928,7 +1004,6 @@ class biModelTest extends baseTest { $result = $this->instance->downloadDuckdb(); if(dao::isError()) return dao::getError(); - return $result; } @@ -2942,7 +1017,6 @@ class biModelTest extends baseTest { $result = $this->instance->checkDuckdbInstall(); if(dao::isError()) return dao::getError(); - return $result; } @@ -2958,7 +1032,6 @@ class biModelTest extends baseTest { $result = $this->instance->updateDownloadingTagFile($type, $action); if(dao::isError()) return dao::getError(); - return $result; } @@ -2975,7 +1048,6 @@ class biModelTest extends baseTest { $result = $this->instance->unzipFile($path, $file, $extractFile); if(dao::isError()) return dao::getError(); - return $result; } @@ -2990,49 +1062,9 @@ class biModelTest extends baseTest */ public function downloadFileTest(string $url, string $savePath, string $finalFile) { - // 由于 downloadFile 方法依赖外部网络资源和文件系统,直接使用 mock 实现进行测试 - return $this->mockDownloadFile($url, $savePath, $finalFile); - } - - /** - * Mock downloadFile method for testing. - * - * @param string $url - * @param string $savePath - * @param string $finalFile - * @access private - * @return bool - */ - private function mockDownloadFile(string $url, string $savePath, string $finalFile): bool - { - // 空参数测试 - if(empty($url) || empty($savePath) || empty($finalFile)) return false; - - // 无效URL测试 - if(!filter_var($url, FILTER_VALIDATE_URL)) return false; - - // 不可达URL测试 - if(strpos($url, 'invalid-domain.test') !== false) return false; - - // 不存在目录测试 - if(strpos($savePath, '/nonexistent/') !== false) return false; - - // 404错误测试 - if(strpos($url, '/status/404') !== false) return false; - - // JSON格式错误测试 - if(strpos($url, '/json-error') !== false) return false; - - // 文件保存失败测试 - if(strpos($savePath, '/readonly/') !== false) return false; - - // ZIP文件测试 - if(strpos($url, '.zip') !== false) return true; - - // 正常下载测试 - if(strpos($url, 'httpbin.org') !== false || strpos($url, 'valid-test') !== false) return true; - - return false; + $result = $this->instance->downloadFile($url, $savePath, $finalFile); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -3044,204 +1076,8 @@ class biModelTest extends baseTest */ public function jsonEncodeTest($object) { - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('jsonEncode'); - $method->setAccessible(true); - - $result = $method->invoke($this->instance, $object); + $result = $this->invokeArgs('jsonEncode', [$object]); if(dao::isError()) return dao::getError(); - return $result; } - - /** - * Test fetchAllTables method. - * - * @access public - * @return mixed - */ - public function fetchAllTablesTest() - { - try - { - $reflection = new ReflectionClass($this->objectTao); - $method = $reflection->getMethod('fetchAllTables'); - $method->setAccessible(true); - - $result = $method->invoke($this->objectTao); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 模拟fetchAllTables的返回结果用于测试 - $mockTables = array(); - - // 排除的表(配置中定义的) - $excludedTables = array('zt_action', 'zt_duckdbqueue', 'zt_metriclib', 'zt_repofiles', 'zt_repohistory', 'zt_queue'); - - // 模拟常见的zentao表 - $allTables = array( - 'zt_user', 'zt_product', 'zt_project', 'zt_story', 'zt_task', 'zt_bug', 'zt_build', - 'zt_testcase', 'zt_testtask', 'zt_testrun', 'zt_testreport', 'zt_doc', 'zt_team', - 'zt_acl', 'zt_group', 'zt_grouppriv', 'zt_usergroup', 'zt_company', 'zt_dept', - 'zt_config', 'zt_cron', 'zt_file', 'zt_history', 'zt_lang', 'zt_module', - 'zt_extension', 'zt_effort', 'zt_burn', 'zt_release', 'zt_branch', 'zt_productplan' - ); - - // 生成足够数量的表以达到239个(排除6个后) - for($i = 1; $i <= 208; $i++) - { - $allTables[] = 'zt_table' . $i; - } - - // 过滤掉排除的表 - foreach($allTables as $table) - { - if(!in_array($table, $excludedTables)) - { - $mockTables[$table] = $table; - } - } - - return $mockTables; - } - } - - /** - * Test fetchTableQueue method. - * - * @access public - * @return mixed - */ - public function fetchTableQueueTest() - { - $reflection = new ReflectionClass($this->objectTao); - $method = $reflection->getMethod('fetchTableQueue'); - $method->setAccessible(true); - - $result = $method->invoke($this->objectTao); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test updateSyncTime method. - * - * @param array $tables - * @access public - * @return mixed - */ - public function updateSyncTimeTest($tables) - { - if(empty($tables)) - { - $reflection = new ReflectionClass($this->objectTao); - $method = $reflection->getMethod('updateSyncTime'); - $method->setAccessible(true); - - $method->invoke($this->objectTao, $tables); - if(dao::isError()) return dao::getError(); - - return 0; - } - - global $tester; - $dao = $tester->dao; - - $currentTime = helper::now(); - - $reflection = new ReflectionClass($this->objectTao); - $method = $reflection->getMethod('updateSyncTime'); - $method->setAccessible(true); - - $method->invoke($this->objectTao, $tables); - if(dao::isError()) return dao::getError(); - - $updatedCount = $dao->select('COUNT(*)')->from(TABLE_DUCKDBQUEUE) - ->where('object')->in($tables) - ->andWhere('syncTime')->ge($currentTime) - ->fetch('COUNT(*)'); - - return $updatedCount; - } - - /** - * Test fetchActionDate method. - * - * @access public - * @return mixed - */ - public function fetchActionDateTest() - { - $reflection = new ReflectionClass($this->objectTao); - $method = $reflection->getMethod('fetchActionDate'); - $method->setAccessible(true); - - $result = $method->invoke($this->objectTao); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test fetchActionDate method and return object type. - * - * @access public - * @return string - */ - public function fetchActionDateObjectTest() - { - $reflection = new ReflectionClass($this->objectTao); - $method = $reflection->getMethod('fetchActionDate'); - $method->setAccessible(true); - - $result = $method->invoke($this->objectTao); - if(dao::isError()) return dao::getError(); - - return is_object($result) ? 'object' : 'not_object'; - } - - /** - * Mock prepareColumns method for testing. - * - * @param string $sql - * @param object $statement - * @param string $driver - * @access private - * @return array - */ - private function mockPrepareColumns($sql, $statement, $driver = 'mysql') - { - // 模拟getSqlTypeAndFields返回值 - list($columnTypes, $columnFields) = $this->mockGetSqlTypeAndFields($sql, $driver); - - // 模拟getParams4Rebuild返回值 - $fieldPairs = array(); - $relatedObjects = array(); - - foreach($columnFields as $field) - { - $fieldPairs[$field] = ucfirst($field); - $relatedObjects[$field] = 'user'; - } - - // 模拟prepareColumns方法的核心逻辑 - $columns = array(); - $clientLang = 'zh-cn'; - foreach($fieldPairs as $field => $langName) - { - $columns[$field] = array( - 'name' => $field, - 'field' => $field, - 'type' => isset($columnTypes->$field) ? $columnTypes->$field : 'string', - 'object' => $relatedObjects[$field], - $clientLang => $langName - ); - } - - return array($columns, $relatedObjects); - } } diff --git a/module/bi/test/lib/tao.class.php b/module/bi/test/lib/tao.class.php index 0ffcce6ea6..978233dec8 100644 --- a/module/bi/test/lib/tao.class.php +++ b/module/bi/test/lib/tao.class.php @@ -8,3052 +8,6 @@ class biTaoTest extends baseTest protected $moduleName = 'bi'; protected $className = 'tao'; - /** - * Parse sql test - * - * @param string $sql - * @access public - * @return array - */ - public function parseSqlTest($sql) - { - $columns = $this->objectModel->parseSql($sql); - - $result = array(); - foreach($columns as $field => $column) - { - if(empty($column['table'])) continue; - - $result[$field] = "{$column['table']['originTable']}=>{$column['table']['column']}"; - } - - arsort($result); - - return $result; - } - - /** - * get expression test. - * - * @param string $table - * @param string $column - * @param string $alias - * @param string $function - * @access public - * @return string - */ - public function getExpressionTest($table = null, $column = null, $alias = null, $function = null) - { - $expression = $this->objectModel->getExpression($table, $column, $alias, $function); - return trim($expression->build($expression)); - } - - /** - * Test buildQueryResultTableColumns method. - * - * @param array $fieldSettings - * @access public - * @return array - */ - public function buildQueryResultTableColumnsTest($fieldSettings) - { - try - { - $result = $this->objectModel->buildQueryResultTableColumns($fieldSettings); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 如果出现数据库连接问题,模拟方法的行为 - return $this->mockBuildQueryResultTableColumns($fieldSettings); - } - } - - /** - * Mock buildQueryResultTableColumns method for testing. - * - * @param array $fieldSettings - * @access private - * @return array - */ - private function mockBuildQueryResultTableColumns($fieldSettings) - { - $cols = array(); - $clientLang = 'zh-cn'; // 模拟默认语言 - - foreach($fieldSettings as $field => $settings) - { - $settings = (array)$settings; - $title = isset($settings[$clientLang]) ? $settings[$clientLang] : $field; - $type = $settings['type']; - - $cols[] = array('name' => $field, 'title' => $title, 'sortType' => false); - } - - return $cols; - } - - /** - * get condition test. - * - * @param mixed $tableA - * @param mixed $columnA - * @param string $operator - * @param mixed $tableB - * @param mixed $columnB - * @param int $group - * @access public - * @return string - */ - public function getConditionTest(mixed $tableA = null, mixed $columnA = null, string $operator = '', mixed $tableB = null, mixed $columnB = null, int $group = 1, bool $quote = true): string - { - $condition = $this->objectModel->getCondition($tableA, $columnA, $operator, $tableB, $columnB, $group, $quote); - return $condition->build($condition); - } - - /** - * build SQL test. - * - * @param array $args - * @access public - * @return string - */ - public function buildSQLTest(array $args): string - { - $selects = zget($args, 'selects', array()); - $from = zget($args, 'from', array()); - $joins = zget($args, 'joins', array()); - $functions = zget($args, 'functions', array()); - $wheres = zget($args, 'wheres', array()); - $querys = zget($args, 'querys', array()); - $groups = zget($args, 'groups', array()); - $statement = $this->objectModel->buildSQL($selects, $from, $joins, $functions, $wheres, $querys, $groups); - return str_replace(PHP_EOL, '', $statement->build()); - } - - /** - * get columns native type - * - * @param string $sql - * @access public - * @return array - */ - public function getColumns($sql) - { - $columns = $this->objectModel->getColumns($sql, 'mysql'); - - $nativeTypes = array(); - foreach($columns as $field => $fieldInfo) - { - $nativeTypes[$field] = $fieldInfo['native_type']; - } - - return $nativeTypes; - } - - /** - * Test getColumns method. - * - * @param string $sql - * @param string $driver - * @param bool $returnOrigin - * @access public - * @return mixed - */ - public function getColumnsTest($sql, $driver = 'mysql', $returnOrigin = false) - { - try - { - // 处理空SQL情况 - if(empty($sql)) return 0; - - // 测试无效驱动 - if($driver == 'invaliddriver') return 0; - - // 模拟原始返回模式 - if($returnOrigin) return 'returnOrigin'; - - // 模拟不同SQL查询的返回结果,避免实际数据库连接问题 - if(strpos($sql, 'select id, name from zt_product') !== false) - { - return array( - 'id' => array('name' => 'id', 'native_type' => 'INT24'), - 'name' => array('name' => 'name', 'native_type' => 'VAR_STRING') - ); - } - - if(strpos($sql, 'select id, name, code') !== false) - { - $result = array( - 'id' => array('name' => 'id', 'native_type' => 'INT24'), - 'name' => array('name' => 'name', 'native_type' => 'VAR_STRING'), - 'code' => array('name' => 'code', 'native_type' => 'VAR_STRING') - ); - // 对于步骤5,返回数组长度 - return count($result); - } - - if(strpos($sql, 'select id, title from zt_bug') !== false) - { - return array( - 'id' => array('name' => 'id', 'native_type' => 'INT24'), - 'title' => array('name' => 'title', 'native_type' => 'VAR_STRING') - ); - } - - // 对于其他复杂查询的模拟 - if(strpos($sql, 'join') !== false) - { - return array( - 'id' => array('name' => 'id', 'native_type' => 'INT24'), - 'name' => array('name' => 'name', 'native_type' => 'VAR_STRING'), - 'title' => array('name' => 'title', 'native_type' => 'VAR_STRING') - ); - } - - // 尝试实际调用(如果测试环境允许) - $result = $this->objectModel->getColumns($sql, $driver, $returnOrigin); - if(dao::isError()) return dao::getError(); - - // 处理无效驱动的情况 - if($result === false) return 0; - - return $result; - } - catch(Exception $e) - { - return 0; - } - } - - /** - * get tables and fields - * - * @param string $sql - * @access public - * @return array - */ - public function getTableAndFields($sql) - { - // 总是使用mock模式,确保测试稳定 - return $this->mockGetTableAndFields($sql); - } - - /** - * Test getTables method. - * - * @param string $sql - * @param bool $deep - * @access public - * @return array - */ - public function getTablesTest($sql, $deep = false) - { - $statement = $this->objectModel->parseToStatement($sql); - if(dao::isError()) return dao::getError(); - - if(!$statement) return array(); - - $result = $this->objectModel->getTables($statement, $deep); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Mock getTableAndFields method for testing. - * - * @param string $sql - * @access private - * @return array|int - */ - private function mockGetTableAndFields($sql) - { - // 处理无效SQL - if(empty($sql) || !is_string($sql)) return 0; - - $sql = trim($sql); - - // 检查是否是有效的SELECT语句 - if(stripos($sql, 'SELECT') !== 0) return 0; - - // 特殊处理:无效SQL语句 - if($sql === 'INVALID SQL STATEMENT') return 0; - - // 处理各种SQL语句 - $tables = array(); - $fields = array(); - - // 处理: SELECT id, name FROM zt_user - if(preg_match('/SELECT\s+(.+?)\s+FROM\s+(\S+)/i', $sql, $matches)) - { - $fieldsList = trim($matches[1]); - $tableName = trim($matches[2]); - - // 解析表名 - if(preg_match('/^(\w+)/', $tableName, $tableMatch)) - { - $tables[] = $tableMatch[1]; - } - - // 解析字段 - if($fieldsList === '*') - { - // 处理SELECT * - $fields['*'] = '*'; - } - else - { - // 处理具体字段 - $fieldsArray = explode(',', $fieldsList); - foreach($fieldsArray as $field) - { - $field = trim($field); - // 移除表别名前缀(如 u.id -> id) - if(strpos($field, '.') !== false) - { - $field = substr($field, strpos($field, '.') + 1); - } - $fields[$field] = $field; - } - } - } - - // 处理连接查询: SELECT u.id, p.name FROM zt_user u LEFT JOIN zt_project p ON ... - if(preg_match('/FROM\s+(\w+)\s+\w+\s+.*?JOIN\s+(\w+)/i', $sql, $joinMatches)) - { - $tables = array($joinMatches[1], $joinMatches[2]); - } - - // 处理子查询: SELECT * FROM (SELECT id FROM zt_user) sub - if(preg_match('/FROM\s*\(.*?FROM\s+(\w+).*?\)/i', $sql, $subMatches)) - { - $tables = array($subMatches[1]); - } - - return array('tables' => array_unique($tables), 'fields' => $fields); - } - - /** - * Test process vars. - * - * @param string $sql - * @param array $filters - * @param bool $emptyValue - * @access public - * @return string - */ - public function processVarsTest($sql, $filters, $emptyValue) - { - return $this->objectModel->processVars($sql, $filters, $emptyValue); - } - - /** - * Test prepareBuiltinPivot. - * - * @param string $operate - * @access public - * @return string - */ - public function prepareBuiltinPivotSQLTest($operate) - { - return $this->objectModel->prepareBuiltinPivotSQL($operate); - } - - /** - * Test prepareBuiltinChartSQL method. - * - * @param string $operate - * @access public - * @return array - */ - public function prepareBuiltinChartSQLTest($operate) - { - global $config; - - // 模拟配置加载 - if(!isset($config->bi)) - { - include dirname(__FILE__, 3) . '/config.php'; - include dirname(__FILE__, 3) . '/config/charts.php'; - } - - $charts = $config->bi->builtin->charts; - - $chartSQLs = array(); - foreach($charts as $chart) - { - $currentOperate = $operate; - $chart = (object)$chart; - $chart->mode = 'text'; - - // JSON编码处理 - if(isset($chart->settings)) $chart->settings = json_encode($chart->settings); - if(isset($chart->filters)) $chart->filters = json_encode($chart->filters); - if(isset($chart->fields)) $chart->fields = json_encode($chart->fields); - if(isset($chart->langs)) $chart->langs = json_encode($chart->langs); - if(!isset($chart->driver)) $chart->driver = 'mysql'; - - // 模拟数据库查询检查记录是否存在 - $exists = false; // 对于测试,假设都不存在 - if(!$exists) $currentOperate = 'insert'; - - $stmt = null; - if($currentOperate == 'insert') - { - $chart->createdBy = 'system'; - $chart->createdDate = date('Y-m-d H:i:s'); - $chart->group = 0; // 模拟getCorrectGroup返回值 - - // 生成模拟的插入SQL - $chartSQLs[] = sprintf( - "INSERT INTO `zt_chart` (`id`, `name`, `code`, `dimension`, `type`, `group`, `sql`, `settings`, `filters`, `stage`, `builtin`, `mode`, `driver`, `createdBy`, `createdDate`) VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')", - $chart->id, - addslashes($chart->name), - addslashes($chart->code), - $chart->dimension, - $chart->type, - $chart->group, - addslashes($chart->sql), - addslashes($chart->settings), - addslashes($chart->filters), - $chart->stage, - $chart->builtin, - $chart->mode, - $chart->driver, - $chart->createdBy, - $chart->createdDate - ); - } - if($currentOperate == 'update') - { - $id = $chart->id; - // 生成模拟的更新SQL - $chartSQLs[] = sprintf( - "UPDATE `zt_chart` SET `name` = '%s', `code` = '%s', `dimension` = '%s', `type` = '%s', `sql` = '%s', `settings` = '%s', `filters` = '%s', `stage` = '%s', `builtin` = '%s', `mode` = '%s', `driver` = '%s' WHERE `id` = %d", - addslashes($chart->name), - addslashes($chart->code), - $chart->dimension, - $chart->type, - addslashes($chart->sql), - addslashes($chart->settings), - addslashes($chart->filters), - $chart->stage, - $chart->builtin, - $chart->mode, - $chart->driver, - $id - ); - } - } - - return $chartSQLs; - } - - /** - * Test getViewableObject method. - * - * @param string $objectType - * @access public - * @return mixed - */ - public function getViewableObjectTest($objectType) - { - $result = $this->objectModel->getViewableObject($objectType); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test parseToStatement method. - * - * @param string $sql - * @access public - * @return mixed - */ - public function parseToStatementTest($sql) - { - $result = $this->objectModel->parseToStatement($sql); - if(dao::isError()) return dao::getError(); - - if($result === false) return false; - if(is_object($result)) return 'object'; - - return $result; - } - - - /** - * Test getFields method. - * - * @param object $statement - * @access public - * @return mixed - */ - public function getFieldsTest($statement) - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->objectModel === null) - { - return $this->mockGetFields($statement); - } - - try - { - $result = $this->objectModel->getFields($statement); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟getFields方法的行为 - return $this->mockGetFields($statement); - } - } - - /** - * Mock getFields method for testing. - * - * @param object $statement - * @access private - * @return array - */ - private function mockGetFields($statement) - { - if(!$statement->expr) return array(); - - $fields = array(); - foreach($statement->expr as $fieldInfo) - { - $field = $fieldInfo->expr; - $alias = $field; - if(!empty($fieldInfo->alias)) - { - $alias = $fieldInfo->alias; - } - elseif(strrpos($field, '.') !== false) - { - $alias = explode('.', $field)[1]; - } - $fields[$alias] = $field; - } - return $fields; - } - - /** - * Test parseTableList method. - * - * @param string $sql - * @access public - * @return mixed - */ - public function parseTableListTest($sql) - { - $result = $this->objectModel->parseTableList($sql); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test getFieldsWithTable method. - * - * @param string $sql - * @access public - * @return mixed - */ - public function getFieldsWithTableTest($sql) - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->objectModel === null) - { - return $this->mockGetFieldsWithTable($sql); - } - - try - { - $result = $this->objectModel->getFieldsWithTable($sql); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟getFieldsWithTable方法的行为 - return $this->mockGetFieldsWithTable($sql); - } - } - - /** - * Mock getFieldsWithTable method for testing. - * - * @param string $sql - * @access private - * @return array - */ - private function mockGetFieldsWithTable($sql) - { - // 处理无效SQL - if(empty($sql) || strpos(strtoupper(trim($sql)), 'SELECT') !== 0) - { - return array(); - } - - // 模拟解析SQL语句 - $sql = trim($sql); - - // 处理: SELECT id, account, realname FROM zt_user - if(preg_match('/SELECT\s+id,\s*account,\s*realname\s+FROM\s+zt_user$/i', $sql)) - { - return array('id' => 'zt_user', 'account' => 'zt_user', 'realname' => 'zt_user'); - } - - // 处理: SELECT u.id, u.account, u.realname FROM zt_user u - if(preg_match('/SELECT\s+u\.id,\s*u\.account,\s*u\.realname\s+FROM\s+zt_user\s+u$/i', $sql)) - { - return array('id' => 'zt_user', 'account' => 'zt_user', 'realname' => 'zt_user'); - } - - // 处理: SELECT u.account, p.name FROM zt_user u LEFT JOIN zt_product p ON u.id = p.id - if(preg_match('/SELECT\s+u\.account,\s*p\.name\s+FROM\s+zt_user\s+u\s+LEFT\s+JOIN\s+zt_product\s+p/i', $sql)) - { - return array('account' => 'zt_user', 'name' => 'zt_product'); - } - - // 处理: SELECT u.account AS user_account, u.realname AS user_name FROM zt_user u - if(preg_match('/SELECT\s+u\.account\s+AS\s+user_account,\s*u\.realname\s+AS\s+user_name\s+FROM\s+zt_user\s+u$/i', $sql)) - { - return array('user_account' => 'zt_user', 'user_name' => 'zt_user'); - } - - // 处理: SELECT * FROM zt_user - if(preg_match('/SELECT\s+\*\s+FROM\s+zt_user$/i', $sql)) - { - // 模拟zt_user表的常见字段 - return array( - 'id' => 'zt_user', - 'account' => 'zt_user', - 'password' => 'zt_user', - 'role' => 'zt_user', - 'realname' => 'zt_user', - 'nickname' => 'zt_user', - 'avatar' => 'zt_user', - 'birthday' => 'zt_user', - 'gender' => 'zt_user', - 'email' => 'zt_user', - 'skype' => 'zt_user', - 'qq' => 'zt_user', - 'yahoo' => 'zt_user', - 'gtalk' => 'zt_user', - 'wangwang' => 'zt_user', - 'mobile' => 'zt_user', - 'phone' => 'zt_user', - 'address' => 'zt_user', - 'zipcode' => 'zt_user', - 'join' => 'zt_user', - 'visits' => 'zt_user', - 'ip' => 'zt_user', - 'last' => 'zt_user', - 'fails' => 'zt_user', - 'locked' => 'zt_user', - 'feedback' => 'zt_user', - 'ranzhi' => 'zt_user', - 'score' => 'zt_user', - 'scoreLevel' => 'zt_user', - 'deleted' => 'zt_user', - 'clientStatus' => 'zt_user', - 'clientLang' => 'zt_user' - ); - } - - // 处理: SELECT u.*, p.name FROM zt_user u INNER JOIN zt_product p ON u.id = p.createdBy - if(preg_match('/SELECT\s+u\.\*,\s*p\.name\s+FROM\s+zt_user\s+u\s+INNER\s+JOIN\s+zt_product\s+p/i', $sql)) - { - // u.*会展开成zt_user表的所有字段,再加上p.name - $userFields = array( - 'id' => 'zt_user', - 'account' => 'zt_user', - 'password' => 'zt_user', - 'role' => 'zt_user', - 'realname' => 'zt_user', - 'nickname' => 'zt_user', - 'avatar' => 'zt_user', - 'birthday' => 'zt_user', - 'gender' => 'zt_user', - 'email' => 'zt_user', - 'skype' => 'zt_user', - 'qq' => 'zt_user', - 'yahoo' => 'zt_user', - 'gtalk' => 'zt_user', - 'wangwang' => 'zt_user', - 'mobile' => 'zt_user', - 'phone' => 'zt_user', - 'address' => 'zt_user', - 'zipcode' => 'zt_user', - 'join' => 'zt_user', - 'visits' => 'zt_user', - 'ip' => 'zt_user', - 'last' => 'zt_user', - 'fails' => 'zt_user', - 'locked' => 'zt_user', - 'feedback' => 'zt_user', - 'ranzhi' => 'zt_user', - 'score' => 'zt_user', - 'scoreLevel' => 'zt_user', - 'deleted' => 'zt_user', - 'clientStatus' => 'zt_user', - 'clientLang' => 'zt_user' - ); - $userFields['name'] = 'zt_product'; - return $userFields; - } - - // 默认返回空数组 - return array(); - } - - /** - * Test getFieldsWithAlias method. - * - * @param string $sql - * @access public - * @return mixed - */ - public function getFieldsWithAliasTest($sql) - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->objectModel === null) - { - return $this->mockGetFieldsWithAlias($sql); - } - - try - { - $result = $this->objectModel->getFieldsWithAlias($sql); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - return $this->mockGetFieldsWithAlias($sql); - } - } - - /** - * Mock getFieldsWithAlias method for testing. - * - * @param string $sql - * @access private - * @return array - */ - private function mockGetFieldsWithAlias($sql) - { - // 处理无效SQL - if(empty($sql) || strpos(strtoupper(trim($sql)), 'SELECT') !== 0) - { - return array(); - } - - // 解析不同类型的SQL语句 - $sql = trim($sql); - - // 处理: SELECT id, account, realname FROM zt_user - if(preg_match('/SELECT\s+id,\s*account,\s*realname\s+FROM\s+zt_user$/i', $sql)) - { - return array('id' => 'id', 'account' => 'account', 'realname' => 'realname'); - } - - // 处理: SELECT id AS user_id, account AS username FROM zt_user - if(preg_match('/SELECT\s+id\s+AS\s+user_id,\s*account\s+AS\s+username\s+FROM\s+zt_user$/i', $sql)) - { - return array('user_id' => 'id', 'username' => 'account'); - } - - // 处理: SELECT u.id, u.account, u.realname FROM zt_user u - if(preg_match('/SELECT\s+u\.id,\s*u\.account,\s*u\.realname\s+FROM\s+zt_user\s+u$/i', $sql)) - { - return array('id' => 'id', 'account' => 'account', 'realname' => 'realname'); - } - - // 处理: SELECT u.account, p.name FROM zt_user u LEFT JOIN zt_product p ON u.id = p.id - if(preg_match('/SELECT\s+u\.account,\s*p\.name\s+FROM\s+zt_user\s+u\s+LEFT\s+JOIN\s+zt_product\s+p/i', $sql)) - { - return array('account' => 'account', 'name' => 'name'); - } - - // 默认返回空数组 - return array(); - } - - /** - * Test getTableByAlias method. - * - * @param mixed $statement - * @param string $alias - * @access public - * @return mixed - */ - public function getTableByAliasTest($statement, $alias) - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->objectModel === null) - { - return $this->mockGetTableByAlias($statement, $alias); - } - - try - { - $result = $this->objectModel->getTableByAlias($statement, $alias); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟getTableByAlias方法的行为 - return $this->mockGetTableByAlias($statement, $alias); - } - } - - /** - * Mock getTableByAlias method for testing. - * - * @param mixed $statement - * @param string $alias - * @access private - * @return mixed - */ - private function mockGetTableByAlias($statement, $alias) - { - $table = false; - if($statement->from) - { - foreach($statement->from as $fromInfo) if($fromInfo->alias == $alias) $table = $fromInfo->table; - } - if($statement->join) - { - foreach($statement->join as $joinInfo) if($joinInfo->expr->alias == $alias) $table = $joinInfo->expr->table; - } - return $table; - } - - /** - * Test explainSQL method. - * - * @param string $sql - * @param string $driver - * @access public - * @return mixed - */ - public function explainSQLTest($sql, $driver = 'mysql') - { - $result = $this->objectModel->explainSQL($sql, $driver); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test getColumnsType method. - * - * @param string $sql - * @param string $driverName - * @param array $columns - * @access public - * @return mixed - */ - public function getColumnsTypeTest($sql, $driverName = 'mysql', $columns = array()) - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->objectModel === null) - { - return $this->mockGetColumnsType($sql, $driverName, $columns); - } - - try - { - $result = $this->objectModel->getColumnsType($sql, $driverName, $columns); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - return $this->mockGetColumnsType($sql, $driverName, $columns); - } - } - - /** - * Mock getColumnsType method for testing. - * - * @param string $sql - * @param string $driverName - * @param array $columns - * @access private - * @return object - */ - private function mockGetColumnsType($sql, $driverName = 'mysql', $columns = array()) - { - $columnTypes = new stdclass(); - - // 根据SQL语句中的字段名推断字段类型 - if(stripos($sql, 'id') !== false) - { - $columnTypes->id = 'number'; - } - - if(stripos($sql, 'account') !== false) - { - $columnTypes->account = 'string'; - } - - if(stripos($sql, 'realname') !== false) - { - $columnTypes->realname = 'string'; - } - - if(stripos($sql, 'role') !== false) - { - $columnTypes->role = 'string'; - } - - if(stripos($sql, 'total') !== false || stripos($sql, 'count(') !== false) - { - $columnTypes->total = 'string'; - } - - return $columnTypes; - } - - /** - * Test getScopeOptions method. - * - * @param string $type - * @access public - * @return mixed - */ - public function getScopeOptionsTest($type) - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->objectModel === null) - { - return $this->mockGetScopeOptions($type); - } - - try - { - $result = $this->objectModel->getScopeOptions($type); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟getScopeOptions方法的行为 - return $this->mockGetScopeOptions($type); - } - } - - /** - * Mock getScopeOptions method for testing. - * - * @param string $type - * @access private - * @return array - */ - private function mockGetScopeOptions($type) - { - $options = array(); - switch($type) - { - case 'user': - $options = array( - 'admin' => '管理员', - 'user1' => '用户1', - 'user2' => '用户2', - 'user3' => '用户3', - 'user4' => '用户4' - ); - break; - case 'product': - $options = array( - '1' => '产品1', - '2' => '产品2', - '3' => '产品3' - ); - break; - case 'project': - // 模拟无项目或空项目情况 - $options = array(); - break; - case 'execution': - $options = array( - '11' => '执行1', - '12' => '执行2', - '13' => '执行3' - ); - break; - case 'dept': - $options = array( - '1' => '/部门1', - '2' => '/部门2', - '3' => '/部门3' - ); - break; - case 'user.status': - // 模拟语言包数据 - $options = array( - 'active' => '正常', - 'deleted' => '已删除', - 'forbidden' => '禁用' - ); - break; - default: - $options = array(); - break; - } - - return $options; - } - - /** - * Test getDataviewOptions method. - * - * @param string $object - * @param string $field - * @access public - * @return mixed - */ - public function getDataviewOptionsTest($object, $field) - { - $result = $this->objectModel->getDataviewOptions($object, $field); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test getObjectOptions method. - * - * @param string $object - * @param string $field - * @access public - * @return mixed - */ - public function getObjectOptionsTest($object, $field) - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->objectModel === null) - { - return $this->mockGetObjectOptions($object, $field); - } - - try - { - $result = $this->objectModel->getObjectOptions($object, $field); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟getObjectOptions方法的行为 - return $this->mockGetObjectOptions($object, $field); - } - } - - /** - * Mock getObjectOptions method for testing. - * - * @param string $object - * @param string $field - * @access private - * @return array - */ - private function mockGetObjectOptions($object, $field) - { - // 处理空参数 - if(empty($object) || empty($field)) return array(); - - // 模拟objectTables配置 - $objectTables = array( - 'user' => 'zt_user', - 'product' => 'zt_product', - 'project' => 'zt_project', - 'story' => 'zt_story', - 'task' => 'zt_task', - 'bug' => 'zt_bug' - ); - - // 不存在的对象类型返回空数组 - if(!isset($objectTables[$object])) return array(); - - $tableName = $objectTables[$object]; - - // 模拟数据库字段 - $tableFields = array( - 'zt_user' => array('id', 'account', 'realname', 'role', 'email'), - 'zt_product' => array('id', 'name', 'code', 'status', 'desc'), - 'zt_project' => array('id', 'name', 'code', 'status', 'desc'), - 'zt_story' => array('id', 'title', 'type', 'status', 'stage'), - 'zt_task' => array('id', 'name', 'type', 'status', 'pri'), - 'zt_bug' => array('id', 'title', 'type', 'status', 'severity') - ); - - $fields = isset($tableFields[$tableName]) ? $tableFields[$tableName] : array('id'); - - // 不存在的字段时使用id字段 - $useField = in_array($field, $fields) ? $field : 'id'; - - // 模拟查询结果 - switch($object) - { - case 'user': - if($useField == 'id') return array('1' => '1', '2' => '2', '3' => '3'); - if($useField == 'account') return array('1' => 'admin', '2' => 'testuser1', '3' => 'testuser2'); - if($useField == 'realname') return array('1' => '管理员', '2' => '测试用户1', '3' => '测试用户2'); - break; - - case 'product': - if($useField == 'id') return array('1' => '1', '2' => '2'); - if($useField == 'name') return array('1' => '正常产品', '2' => '产品2'); - if($useField == 'code') return array('1' => 'product1', '2' => 'product2'); - break; - - default: - return array('1' => '1', '2' => '2'); - } - - return array(); - } - - /** - * Test getOptionsFromSql method. - * - * @param string $sql - * @param string $driver - * @param string $keyField - * @param string $valueField - * @access public - * @return mixed - */ - public function getOptionsFromSqlTest($sql, $driver, $keyField, $valueField) - { - $result = $this->objectModel->getOptionsFromSql($sql, $driver, $keyField, $valueField); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test genWaterpolo method. - * - * @param array $fields - * @param array $settings - * @param string $sql - * @param array $filters - * @access public - * @return mixed - */ - public function genWaterpoloTest($fields, $settings, $sql, $filters) - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->objectModel === null) - { - return $this->mockGenWaterpolo($fields, $settings, $sql, $filters); - } - - try - { - $result = $this->objectModel->genWaterpolo($fields, $settings, $sql, $filters); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟genWaterpolo方法的行为 - return $this->mockGenWaterpolo($fields, $settings, $sql, $filters); - } - } - - /** - * Mock genWaterpolo method for testing. - * - * @param array $fields - * @param array $settings - * @param string $sql - * @param array $filters - * @access private - * @return array - */ - private function mockGenWaterpolo($fields, $settings, $sql, $filters) - { - // 模拟chart配置 - $conditionList = array('eq' => '='); - - $operate = "{$settings['calc']}({$settings['goal']})"; - $sql = "select $operate as count from ($sql) tt "; - - $moleculeSQL = $sql; - $denominatorSQL = $sql; - - $moleculeWheres = array(); - $denominatorWheres = array(); - - foreach($settings['conditions'] as $condition) - { - $where = "{$condition['field']} {$conditionList[$condition['condition']]} '{$condition['value']}'"; - $moleculeWheres[] = $where; - } - - if(!empty($filters)) - { - $wheres = array(); - foreach($filters as $field => $filter) - { - $wheres[] = "$field {$filter['operator']} {$filter['value']}"; - } - $moleculeWheres = array_merge($moleculeWheres, $wheres); - $denominatorWheres = $wheres; - } - - if($moleculeWheres) $moleculeSQL .= 'where ' . implode(' and ', $moleculeWheres); - if($denominatorWheres) $denominatorSQL .= 'where ' . implode(' and ', $denominatorWheres); - - // 模拟查询结果 - $moleculeCount = 0; - $denominatorCount = 0; - - // 根据条件模拟不同的计数结果 - if(empty($settings['conditions'])) - { - // 空条件,模拟查询所有记录 - $moleculeCount = 10; - $denominatorCount = 10; - } - elseif($settings['conditions'][0]['value'] == '999') - { - // 分母为零的测试场景 - $moleculeCount = 0; - $denominatorCount = 0; - } - elseif($settings['conditions'][0]['value'] == '0') - { - // 正常情况,非删除用户 - $moleculeCount = 8; - $denominatorCount = 10; - } - else - { - // 其他情况 - $moleculeCount = 5; - $denominatorCount = 10; - } - - // 如果有过滤器,调整计数 - if(!empty($filters)) - { - $denominatorCount = $moleculeCount; // 分母受过滤器影响 - } - - $percent = $denominatorCount ? round((int)$moleculeCount / (int)$denominatorCount, 4) : 0; - - $series = array(array('type' => 'liquidFill', 'data' => array($percent), 'color' => array('#2e7fff'), 'outline' => array('show' => false), 'label' => array('fontSize' => 26))); - $tooltip = array('show' => true); - $options = array('series' => $series, 'tooltip' => $tooltip); - - return $options; - } - - /** - * Test getMultiData method. - * - * @param array $settings - * @param string $defaultSql - * @param array $filters - * @param string $driver - * @param bool $sort - * @access public - * @return mixed - */ - public function getMultiDataTest($settings, $defaultSql, $filters, $driver, $sort = false) - { - $result = $this->objectModel->getMultiData($settings, $defaultSql, $filters, $driver, $sort); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test getTableFields method. - * - * @access public - * @return mixed - */ - public function getTableFieldsTest() - { - // 如果model未初始化(数据库连接失败),返回mock数据用于测试 - if($this->objectModel === null) - { - return 'array'; - } - - $result = $this->objectModel->getTableFields(); - if(dao::isError()) return dao::getError(); - - return is_array($result) ? 'array' : 'not_array'; - } - - /** - * Test getTableFields method returns not empty. - * - * @access public - * @return string - */ - public function getTableFieldsTestNotEmpty() - { - if($this->objectModel === null) return 'not_empty'; - - $result = $this->objectModel->getTableFields(); - if(dao::isError()) return dao::getError(); - - return !empty($result) ? 'not_empty' : 'empty'; - } - - /** - * Test getTableFields method has tables. - * - * @access public - * @return string - */ - public function getTableFieldsTestHasTables() - { - if($this->objectModel === null) return 'has_tables'; - - $result = $this->objectModel->getTableFields(); - if(dao::isError()) return dao::getError(); - - if(!is_array($result) || empty($result)) return 'no_tables'; - - foreach($result as $table => $fields) - { - if(strpos($table, 'zt_') === 0) return 'has_tables'; - } - - return 'no_tables'; - } - - /** - * Test getTableFields method has fields for each table. - * - * @access public - * @return string - */ - public function getTableFieldsTestHasFields() - { - if($this->objectModel === null) return 'has_fields'; - - $result = $this->objectModel->getTableFields(); - if(dao::isError()) return dao::getError(); - - if(!is_array($result) || empty($result)) return 'no_fields'; - - foreach($result as $table => $fields) - { - if(!is_array($fields) || empty($fields)) return 'no_fields'; - } - - return 'has_fields'; - } - - /** - * Test getTableFields method has valid structure. - * - * @access public - * @return string - */ - public function getTableFieldsTestValidStructure() - { - if($this->objectModel === null) return 'valid_structure'; - - $result = $this->objectModel->getTableFields(); - if(dao::isError()) return dao::getError(); - - if(!is_array($result) || empty($result)) return 'invalid_structure'; - - foreach($result as $table => $fields) - { - if(!is_array($fields)) return 'invalid_structure'; - - foreach($fields as $fieldName => $fieldInfo) - { - if(!is_array($fieldInfo)) return 'invalid_structure'; - if(!isset($fieldInfo['type'])) return 'invalid_structure'; - } - } - - return 'valid_structure'; - } - - /** - * Test getTableFieldsMenu method. - * - * @access public - * @return mixed - */ - public function getTableFieldsMenuTest() - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->objectModel === null) - { - return $this->mockGetTableFieldsMenu(); - } - - try - { - $result = $this->objectModel->getTableFieldsMenu(); - if(dao::isError()) return dao::getError(); - - // 为了测试断言,返回类型标识 - if(is_array($result) && !empty($result)) - { - return 'array'; - } - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,使用mock方式 - return $this->mockGetTableFieldsMenu(); - } - } - - /** - * Mock getTableFieldsMenu method for testing. - * - * @access private - * @return string - */ - private function mockGetTableFieldsMenu() - { - // 模拟getTableFields返回的数据结构 - $tableFields = array( - 'zt_user' => array( - 'id' => array('type' => 'int'), - 'account' => array('type' => 'varchar'), - 'realname' => array('type' => 'varchar') - ), - 'zt_product' => array( - 'id' => array('type' => 'int'), - 'name' => array('type' => 'varchar'), - 'status' => array('type' => 'varchar') - ), - 'zt_project' => array( - 'id' => array('type' => 'int'), - 'name' => array('type' => 'varchar'), - 'status' => array('type' => 'varchar') - ) - ); - - // 模拟getTableFieldsMenu的逻辑 - $menu = array(); - foreach($tableFields as $table => $fields) - { - $tableItem = array(); - $tableItem['key'] = $table; - $tableItem['text'] = $table . '(table)'; - $tableItem['items'] = array(); - - foreach($fields as $field => $fieldInfo) - { - $fieldItem = array(); - $fieldItem['key'] = $field; - $fieldItem['text'] = $field . '(' . $fieldInfo['type'] . ')'; - - $tableItem['items'][] = $fieldItem; - } - - $menu[] = $tableItem; - } - - // 为了测试断言,返回类型标识 - if(is_array($menu) && !empty($menu)) - { - return 'array'; - } - - return $menu; - } - - /** - * Test getTableFieldsMenu method for empty case. - * - * @access public - * @return mixed - */ - public function getTableFieldsMenuTestEmpty() - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->objectModel === null) - { - return $this->mockGetTableFieldsMenuEmpty(); - } - - try - { - // 模拟获取空的表字段情况 - $result = $this->objectModel->getTableFieldsMenu(); - if(dao::isError()) return dao::getError(); - - if(is_array($result) && empty($result)) - { - return 'empty'; - } - - // 如果有数据,返回非空标识(正常情况) - return 'not_empty'; - } - catch(Exception $e) - { - // 当数据库连接失败时,使用mock方式 - return $this->mockGetTableFieldsMenuEmpty(); - } - } - - /** - * Mock getTableFieldsMenu method for empty case testing. - * - * @access private - * @return string - */ - private function mockGetTableFieldsMenuEmpty() - { - // 正常情况下应该有数据,所以返回not_empty - return 'not_empty'; - } - - /** - * Test getTableFieldsMenu method structure validation. - * - * @access public - * @return mixed - */ - public function getTableFieldsMenuTestStructure() - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->objectModel === null) - { - return $this->mockGetTableFieldsMenuStructure(); - } - - try - { - $result = $this->objectModel->getTableFieldsMenu(); - if(dao::isError()) return dao::getError(); - - if(!is_array($result)) return 'invalid_type'; - if(empty($result)) return 'empty'; - - $firstItem = reset($result); - if(!is_array($firstItem)) return 'invalid_structure'; - - // 检查必要的属性 - if(!isset($firstItem['key'])) return 'no_key'; - if(!isset($firstItem['text'])) return 'no_text'; - if(!isset($firstItem['items'])) return 'no_items'; - - return 'valid'; - } - catch(Exception $e) - { - // 当数据库连接失败时,使用mock方式 - return $this->mockGetTableFieldsMenuStructure(); - } - } - - /** - * Mock getTableFieldsMenu method for structure testing. - * - * @access private - * @return string - */ - private function mockGetTableFieldsMenuStructure() - { - // 模拟正确的结构并直接返回valid - return 'valid'; - } - - /** - * Test getTableFieldsMenu method format validation. - * - * @access public - * @return mixed - */ - public function getTableFieldsMenuTestFormat() - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->objectModel === null) - { - return $this->mockGetTableFieldsMenuFormat(); - } - - try - { - $result = $this->objectModel->getTableFieldsMenu(); - if(dao::isError()) return dao::getError(); - - if(!is_array($result) || empty($result)) return 'invalid'; - - $firstItem = reset($result); - - // 检查text格式是否包含(table)后缀 - if(!strpos($firstItem['text'], '(table)')) return 'invalid_table_format'; - - // 检查items中的字段格式 - if(!empty($firstItem['items'])) - { - $firstField = reset($firstItem['items']); - if(!strpos($firstField['text'], '(') || !strpos($firstField['text'], ')')) - { - return 'invalid_field_format'; - } - } - - return 'valid'; - } - catch(Exception $e) - { - // 当数据库连接失败时,使用mock方式 - return $this->mockGetTableFieldsMenuFormat(); - } - } - - /** - * Mock getTableFieldsMenu method for format testing. - * - * @access private - * @return string - */ - private function mockGetTableFieldsMenuFormat() - { - // 模拟正确的格式并直接返回valid - return 'valid'; - } - - /** - * Test getTableFieldsMenu method hierarchy validation. - * - * @access public - * @return mixed - */ - public function getTableFieldsMenuTestHierarchy() - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->objectModel === null) - { - return $this->mockGetTableFieldsMenuHierarchy(); - } - - try - { - $result = $this->objectModel->getTableFieldsMenu(); - if(dao::isError()) return dao::getError(); - - if(!is_array($result) || empty($result)) return 'invalid'; - - $firstItem = reset($result); - - // 检查二级结构 - if(!isset($firstItem['items']) || !is_array($firstItem['items'])) - { - return 'no_hierarchy'; - } - - // 检查items中的项目结构 - if(!empty($firstItem['items'])) - { - $firstField = reset($firstItem['items']); - if(!isset($firstField['key']) || !isset($firstField['text'])) - { - return 'invalid_field_structure'; - } - } - - return 'valid'; - } - catch(Exception $e) - { - // 当数据库连接失败时,使用mock方式 - return $this->mockGetTableFieldsMenuHierarchy(); - } - } - - /** - * Mock getTableFieldsMenu method for hierarchy testing. - * - * @access private - * @return string - */ - private function mockGetTableFieldsMenuHierarchy() - { - // 模拟正确的层级结构并直接返回valid - return 'valid'; - } - - /** - * Test preparePivotObject method. - * - * @param mixed $pivot - * @access public - * @return mixed - */ - public function preparePivotObjectTest($pivot) - { - $result = $this->objectModel->preparePivotObject($pivot); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test prepareBuilitinPivotDrillSQL method. - * - * @param int $pivotID - * @param array $drills - * @param int $version - * @access public - * @return array - */ - public function prepareBuilitinPivotDrillSQLTest($pivotID, $drills, $version) - { - $result = $this->objectModel->prepareBuilitinPivotDrillSQL($pivotID, $drills, $version); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test prepareBuiltinMetricSQL method. - * - * @param string $operate - * @access public - * @return array - */ - public function prepareBuiltinMetricSQLTest($operate = 'insert') - { - $result = $this->objectModel->prepareBuiltinMetricSQL($operate); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test prepareBuiltinScreenSQL method. - * - * @param string $operate - * @access public - * @return mixed - */ - public function prepareBuiltinScreenSQLTest($operate = 'insert') - { - $result = $this->objectModel->prepareBuiltinScreenSQL($operate); - if(dao::isError()) return dao::getError(); - - // 如果是数组且不为空,返回'array'用于测试 - if(is_array($result) && !empty($result)) - { - return 'array'; - } - - // 如果是空数组,返回'empty' - if(is_array($result) && empty($result)) - { - return 'empty'; - } - - return $result; - } - - /** - * Test prepareBuiltinScreenSQL method for SQL content validation. - * - * @param string $operate - * @access public - * @return mixed - */ - public function prepareBuiltinScreenSQLContentTest($operate = 'insert') - { - $result = $this->objectModel->prepareBuiltinScreenSQL($operate); - if(dao::isError()) return dao::getError(); - - if(!is_array($result) || empty($result)) - { - return array(); - } - - // 返回SQL数组用于内容检查 - return $result; - } - - /** - * Test getDuckDBPath method. - * - * @access public - * @return mixed - */ - public function getDuckDBPathTest() - { - $result = $this->objectModel->getDuckDBPath(); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test checkDuckDBFile method. - * - * @param string $path - * @param array $bin - * @access public - * @return mixed - */ - public function checkDuckDBFileTest($path, $bin) - { - try { - // 验证必要的参数键是否存在 - if(!isset($bin['file']) || !isset($bin['extension'])) { - return false; - } - - // 调用模型方法 - $result = $this->objectModel->checkDuckDBFile($path, $bin); - if(dao::isError()) return dao::getError(); - - // 如果返回对象,返回'object'用于断言 - if(is_object($result)) return 'object'; - - return $result; - } catch (Exception $e) { - return false; - } - } - - /** - * Test getDuckdbBinConfig method. - * - * @access public - * @return mixed - */ - public function getDuckdbBinConfigTest() - { - $result = $this->objectModel->getDuckdbBinConfig(); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test getDuckDBTmpDir method. - * - * @param bool $static - * @access public - * @return mixed - */ - public function getDuckDBTmpDirTest($static = false) - { - $result = $this->objectModel->getDuckDBTmpDir($static); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test getSqlByMonth method. - * - * @param string $year - * @param string $month - * @access public - * @return mixed - */ - public function getSqlByMonthTest($year = 'Y', $month = 'm') - { - $result = $this->objectModel->getSqlByMonth($year, $month); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test getActionSyncSql method. - * - * @param string $range - * @access public - * @return mixed - */ - public function getActionSyncSqlTest($range = 'current') - { - $result = $this->objectModel->getActionSyncSql($range); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test initParquet method. - * - * @access public - * @return mixed - */ - public function initParquetTest() - { - $result = $this->objectModel->initParquet(); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test prepareCopySQL method. - * - * @param string $duckdbTmpPath - * @access public - * @return mixed - */ - public function prepareCopySQLTest($duckdbTmpPath) - { - $result = $this->objectModel->prepareCopySQL($duckdbTmpPath); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test prepareSyncCommand method. - * - * @param string $binPath - * @param string $extensionPath - * @param string $copySQL - * @access public - * @return mixed - */ - public function prepareSyncCommandTest($binPath, $extensionPath, $copySQL) - { - $result = $this->objectModel->prepareSyncCommand($binPath, $extensionPath, $copySQL); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test generateParquetFile method. - * - * @access public - * @return mixed - */ - public function generateParquetFileTest() - { - $result = $this->objectModel->generateParquetFile(); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test getLogFile method. - * - * @access public - * @return string - */ - public function getLogFileTest() - { - $result = $this->objectModel->getLogFile(); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test saveLogs method. - * - * @param string $log - * @access public - * @return mixed - */ - public function saveLogsTest($log) - { - $tmpDir = sys_get_temp_dir() . DIRECTORY_SEPARATOR; - $logFile = $tmpDir . 'test_saveLogs_' . date('Ymd') . '.log.php'; - - // 删除现有日志文件以确保测试环境干净 - if(file_exists($logFile)) unlink($logFile); - - // 模拟 saveLogs 方法的逻辑 - $logContent = date('Y-m-d H:i:s') . ' ' . trim($log) . "\n"; - if(!file_exists($logFile)) $logContent = "\n" . $logContent; - - file_put_contents($logFile, $logContent, FILE_APPEND); - - // 检查文件是否被创建 - if(!file_exists($logFile)) return false; - - // 读取文件内容进行验证 - $content = file_get_contents($logFile); - - // 清理测试文件 - if(file_exists($logFile)) unlink($logFile); - - return array( - 'fileExists' => true, - 'hasPhpHeader' => strpos($content, ' strpos($content, 'die();') !== false, - 'hasLogContent' => strpos($content, $log) !== false, - 'hasTimestamp' => preg_match('/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', $content) === 1 - ); - } - - /** - * Test parseSqlVars method. - * - * @param string $sql - * @param array $filters - * @access public - * @return string - */ - public function parseSqlVarsTest($sql, $filters) - { - $result = $this->objectModel->parseSqlVars($sql, $filters); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test sql2Statement method. - * - * @param string $sql - * @param string $mode - * @access public - * @return mixed - */ - public function sql2StatementTest($sql, $mode = 'text') - { - // Mock sql2Statement method behavior - // 简化的SQL解析逻辑 - $sql = trim($sql); - - // 空SQL处理 - if(empty($sql)) - { - if($mode == 'builder') return '请正确配置构建器'; - return '请输入一条正确的SQL语句'; - } - - // 检查多条语句 - if(substr_count($sql, ';') > 1 || (substr_count($sql, ';') == 1 && !preg_match('/;\s*$/', $sql))) - { - return '只能输入一条SQL语句'; - } - - // 检查是否为SELECT语句 - if(!preg_match('/^\s*select\s+/i', $sql)) - { - return '只允许SELECT查询'; - } - - return 'object'; - } - - /** - * Test validateSql method. - * - * @param string $sql - * @param string $driver - * @access public - * @return mixed - */ - public function validateSqlTest($sql, $driver = 'mysql') - { - // 模拟validateSql方法的行为,避免实际数据库操作 - if(empty($sql)) return '请输入一条正确的SQL语句'; - - // 对于简单的有效SQL,直接返回true - if(strpos(strtoupper(trim($sql)), 'SELECT') === 0) - { - // 检查是否有重复字段 - 简单检测 - if(preg_match('/SELECT\s+.*\s+as\s+(\w+).*\s+as\s+\1/i', $sql, $matches)) - { - return "存在重复的字段名: " . $matches[1] . "。建议您:(1)修改 * 查询为具体的字段。(2)使用 as 为字段设置别名。"; - } - - // 检查是否包含不存在的表 - if(strpos($sql, 'zt_nonexistent_table') !== false) - { - return "Table 'zttest.zt_nonexistent_table' doesn't exist"; - } - - return true; - } - - // 非SELECT语句返回语法错误 - return "You have an error in your SQL syntax"; - } - - /** - * Test prepareSqlPager method. - * - * @param object $statement - * @param int $recPerPage - * @param int $pageID - * @param string $driver - * @access public - * @return string - */ - public function prepareSqlPagerTest($statement, $recPerPage, $pageID, $driver = 'mysql') - { - $result = $this->objectModel->prepareSqlPager($statement, $recPerPage, $pageID, $driver); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test prepareColumns method. - * - * @param string $sql - * @param object $statement - * @param string $driver - * @access public - * @return mixed - */ - public function prepareColumnsTest($sql, $statement, $driver = 'mysql') - { - if($this->objectModel === null) - { - return $this->mockPrepareColumns($sql, $statement, $driver); - } - - try - { - $result = $this->objectModel->prepareColumns($sql, $statement, $driver); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - return $this->mockPrepareColumns($sql, $statement, $driver); - } - } - - /** - * Test getSqlTypeAndFields method. - * - * @param string $sql - * @param string $driver - * @access public - * @return mixed - */ - public function getSqlTypeAndFieldsTest($sql, $driver = 'mysql') - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->objectModel === null) - { - return $this->mockGetSqlTypeAndFields($sql, $driver); - } - - try - { - $result = $this->objectModel->getSqlTypeAndFields($sql, $driver); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - return $this->mockGetSqlTypeAndFields($sql, $driver); - } - } - - /** - * Mock getSqlTypeAndFields method for testing. - * - * @param string $sql - * @param string $driver - * @access private - * @return array - */ - private function mockGetSqlTypeAndFields($sql, $driver = 'mysql') - { - // 根据SQL语句分析字段类型 - $columnTypes = new stdclass(); - $columnFields = array(); - - // 处理 SELECT id, account FROM zt_user 类型的SQL - if(preg_match('/SELECT\s+(.+?)\s+FROM\s+/i', $sql, $matches)) - { - $fields = explode(',', $matches[1]); - foreach($fields as $field) - { - $field = trim($field); - - // 移除表别名前缀(如 u.id -> id) - if(strpos($field, '.') !== false) - { - $field = substr($field, strpos($field, '.') + 1); - } - - // 根据字段名推断类型 - if($field == 'id') - { - $columnTypes->id = 'number'; - $columnFields['id'] = 'id'; - } - elseif($field == 'account') - { - $columnTypes->account = 'string'; - $columnFields['account'] = 'account'; - } - elseif(in_array($field, array('realname', 'name', 'title', 'desc'))) - { - $columnTypes->$field = 'string'; - $columnFields[$field] = $field; - } - else - { - // 默认为字符串类型 - $columnTypes->$field = 'string'; - $columnFields[$field] = $field; - } - } - } - - return array($columnTypes, $columnFields); - } - - /** - * Test getParams4Rebuild method. - * - * @param string $sql - * @param object $statement - * @param array $columnFields - * @access public - * @return mixed - */ - public function getParams4RebuildTest($sql, $statement, $columnFields) - { - // Mock返回值来测试方法的基本逻辑,避免数据库依赖 - $tableAndFields = array('tables' => array(), 'fields' => array()); - - // 模拟getTableAndFields的结果 - if($statement && $statement->expr) - { - $fields = array(); - foreach($statement->expr as $expr) - { - $field = $expr->expr; - $alias = $field; - if(!empty($expr->alias)) - { - $alias = $expr->alias; - } - elseif(strrpos($field, '.') !== false) - { - $alias = explode('.', $field)[1]; - } - $fields[$alias] = $field; - } - $tableAndFields['fields'] = $fields; - } - - $moduleNames = array(); - $aliasNames = array(); - $fieldPairs = array(); - $relatedObjects = array(); - - // 模拟dataview->mergeFields的简单实现 - foreach($columnFields as $field => $value) - { - $fieldPairs[$field] = $value; - $relatedObjects[$field] = ''; - } - - // 如果字段列表为空,使用SQL解析的字段 - if(empty($fieldPairs) && !empty($tableAndFields['fields'])) - { - foreach($tableAndFields['fields'] as $alias => $field) - { - $fieldPairs[$alias] = $alias; - $relatedObjects[$alias] = ''; - } - } - - // 应用字符过滤逻辑,与原方法保持一致 - foreach($fieldPairs as $field => $name) - { - $fieldPairs[$field] = preg_replace('/[^\x{4e00}-\x{9fa5}0-9a-zA-Z_]/u', '', $name); - } - - return array($moduleNames, $aliasNames, $fieldPairs, $relatedObjects); - } - - /** - * Test getSQL method. - * - * @param string $sql - * @param string $driver - * @param int $recPerPage - * @param int $pageID - * @access public - * @return mixed - */ - public function getSQLTest($sql, $driver = 'mysql', $recPerPage = 10, $pageID = 1) - { - // 直接模拟getSQL方法的核心逻辑,避免复杂的依赖 - try - { - // 模拟sql2Statement的行为 - 创建一个基础的statement对象 - $statement = new stdclass(); - $statement->limit = null; - $statement->options = new stdclass(); - $statement->options->options = array(); - - // 模拟prepareSqlPager的逻辑 - if(!$statement->limit) - { - $statement->limit = new stdclass(); - } - $statement->limit->offset = $recPerPage * ($pageID - 1); - $statement->limit->rowCount = $recPerPage; - - if($driver == 'mysql') $statement->options->options[] = 'SQL_CALC_FOUND_ROWS'; - - // 模拟build()方法的返回值 - $offset = $recPerPage * ($pageID - 1); - $limitSql = $driver == 'mysql' - ? "SELECT SQL_CALC_FOUND_ROWS * FROM ($sql) LIMIT $offset, $recPerPage" - : "$sql LIMIT $offset, $recPerPage"; - - // 根据驱动类型生成countSql - $countSql = "SELECT FOUND_ROWS() AS count"; - if($driver == 'duckdb') $countSql = "SELECT COUNT(1) AS count FROM ($sql)"; - if($driver == 'dm') $countSql = "SELECT COUNT(1) as count FROM ($sql)"; - - $result = array($limitSql, $countSql); - - // 确保结果是一个数组,包含两个元素 - if(!is_array($result) || count($result) != 2) return 0; - - return count($result); - } - catch(Exception $e) - { - return 0; - } - } - - /** - * Test querySQL method. - * - * @param string $sql - * @param string $limitSql - * @param string $driver - * @access public - * @return mixed - */ - public function querySQLTest($sql, $limitSql, $driver = 'mysql') - { - try - { - $result = $this->objectModel->querySQL($sql, $limitSql, $driver); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - return array('result' => 'fail', 'message' => $e->getMessage()); - } - } - - /** - * Test query method. - * - * @param mixed $sqlOrStateObj - * @param string $driver - * @param bool $useFilter - * @access public - * @return mixed - */ - public function queryTest($sqlOrStateObj, $driver = 'mysql', $useFilter = true) - { - // 直接模拟query方法的基本验证逻辑,避免实际数据库操作 - if(is_string($sqlOrStateObj)) - { - $sql = $sqlOrStateObj; - } - else if(is_object($sqlOrStateObj) && isset($sqlOrStateObj->sql)) - { - $sql = $sqlOrStateObj->sql; - } - else - { - return 1; // 无效参数 - } - - // 空SQL检测 - if(empty($sql)) return 1; - - // SQL语法基本检测 - $sql = trim($sql); - $sqlUpper = strtoupper($sql); - - // 检查是否为SELECT语句 - if(strpos($sqlUpper, 'SELECT') !== 0) return 1; - - // 检查无效关键字 - if(strpos($sqlUpper, 'INVALID') !== false) return 1; - if(strpos($sqlUpper, 'INSERT') !== false) return 1; - if(strpos($sqlUpper, 'UPDATE') !== false) return 1; - if(strpos($sqlUpper, 'DELETE') !== false) return 1; - - // 对于某些驱动的特殊处理 - if($driver == 'duckdb') - { - // DuckDB驱动下简单SQL应该能正常工作 - return 0; - } - - // 基本的有效SQL检测 - if($sqlUpper == 'SELECT 1 AS TEST_COL' || - $sqlUpper == 'SELECT COUNT(*) AS TOTAL FROM ZT_USER') - { - return 0; - } - - // 其他有效的SELECT语句 - if(preg_match('/^SELECT\s+.+/', $sqlUpper)) - { - return 0; - } - - return 1; - } - - /** - * Test getTableList method. - * - * @param bool $hasDataview - * @param bool $withPrefix - * @access public - * @return mixed - */ - public function getTableListTest($hasDataview = true, $withPrefix = true) - { - // Due to database initialization issues in test environment, - // we provide a mock implementation that simulates the expected behavior - $tableList = array(); - - // Mock original tables with proper prefix - $prefix = $withPrefix ? 'zt_' : ''; - $tableList[$prefix . 'user'] = '用户'; - $tableList[$prefix . 'product'] = '产品'; - $tableList[$prefix . 'project'] = '项目'; - $tableList[$prefix . 'story'] = '需求'; - $tableList[$prefix . 'task'] = '任务'; - - // Mock dataview tables if requested - if($hasDataview) { - $dataviewPrefix = $withPrefix ? 'ztv_' : ''; - $tableList[$dataviewPrefix . 'user_view'] = '用户视图'; - $tableList[$dataviewPrefix . 'product_view'] = '产品视图'; - } - - return $tableList; - } - - /** - * Test prepareFieldObjects method. - * - * @access public - * @return mixed - */ - public function prepareFieldObjectsTest() - { - try - { - /* Enhanced mock data to ensure comprehensive test coverage */ - $mockResult = array( - array('text' => '产品', 'value' => 'product', 'fields' => array()), - array('text' => '软件需求', 'value' => 'story', 'fields' => array()), - array('text' => '版本', 'value' => 'build', 'fields' => array()), - array('text' => '产品计划', 'value' => 'productplan', 'fields' => array()), - array('text' => '发布', 'value' => 'release', 'fields' => array()), - array('text' => 'Bug', 'value' => 'bug', 'fields' => array()), - array('text' => '项目', 'value' => 'project', 'fields' => array()), - array('text' => '任务', 'value' => 'task', 'fields' => array()), - ); - - /* Try to call the actual method, fall back to mock if it fails */ - try { - $result = $this->objectModel->prepareFieldObjects(); - if(dao::isError() || empty($result)) return $mockResult; - return $result; - } catch(Exception $e) { - return $mockResult; - } catch(Error $e) { - return $mockResult; - } catch(Throwable $e) { - return $mockResult; - } - } - catch(Exception $e) - { - /* Return mock data instead of throwing exception to avoid test failures */ - return array( - array('text' => '产品', 'value' => 'product', 'fields' => array()), - array('text' => '软件需求', 'value' => 'story', 'fields' => array()), - array('text' => '版本', 'value' => 'build', 'fields' => array()), - array('text' => '产品计划', 'value' => 'productplan', 'fields' => array()), - array('text' => '发布', 'value' => 'release', 'fields' => array()), - array('text' => 'Bug', 'value' => 'bug', 'fields' => array()), - array('text' => '项目', 'value' => 'project', 'fields' => array()), - array('text' => '任务', 'value' => 'task', 'fields' => array()), - ); - } - catch(Error $e) - { - /* Handle fatal errors gracefully with mock data */ - return array( - array('text' => '产品', 'value' => 'product', 'fields' => array()), - array('text' => '软件需求', 'value' => 'story', 'fields' => array()), - array('text' => '版本', 'value' => 'build', 'fields' => array()), - array('text' => '产品计划', 'value' => 'productplan', 'fields' => array()), - array('text' => '发布', 'value' => 'release', 'fields' => array()), - array('text' => 'Bug', 'value' => 'bug', 'fields' => array()), - array('text' => '项目', 'value' => 'project', 'fields' => array()), - array('text' => '任务', 'value' => 'task', 'fields' => array()), - ); - } - catch(Throwable $e) - { - /* Handle any other throwable errors with mock data */ - return array( - array('text' => '产品', 'value' => 'product', 'fields' => array()), - array('text' => '软件需求', 'value' => 'story', 'fields' => array()), - array('text' => '版本', 'value' => 'build', 'fields' => array()), - array('text' => '产品计划', 'value' => 'productplan', 'fields' => array()), - array('text' => '发布', 'value' => 'release', 'fields' => array()), - array('text' => 'Bug', 'value' => 'bug', 'fields' => array()), - array('text' => '项目', 'value' => 'project', 'fields' => array()), - array('text' => '任务', 'value' => 'task', 'fields' => array()), - ); - } - } - - /** - * Test prepareFieldSettingFormData method. - * - * @param mixed $settings - * @access public - * @return mixed - */ - public function prepareFieldSettingFormDataTest($settings) - { - $result = $this->objectModel->prepareFieldSettingFormData($settings); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test rebuildFieldSettings method. - * - * @param array $fieldPairs - * @param object $columns - * @param array $relatedObject - * @param object|array $fieldSettings - * @param array $objectFields - * @access public - * @return mixed - */ - public function rebuildFieldSettingsTest($fieldPairs, $columns, $relatedObject, $fieldSettings, $objectFields) - { - $result = $this->objectModel->rebuildFieldSettings($fieldPairs, $columns, $relatedObject, $fieldSettings, $objectFields); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test convertDataForDtable method. - * - * @param object $data - * @param array $configs - * @param string $version - * @param string $status - * @access public - * @return mixed - */ - public function convertDataForDtableTest($data, $configs, $version, $status) - { - // 如果模型对象为null(数据库连接失败),直接使用mock模式 - if($this->objectModel === null) - { - return $this->mockConvertDataForDtable($data, $configs, $version, $status); - } - - try - { - $result = $this->objectModel->convertDataForDtable($data, $configs, $version, $status); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟convertDataForDtable方法的行为 - return $this->mockConvertDataForDtable($data, $configs, $version, $status); - } - } - - /** - * Mock convertDataForDtable method for testing when database unavailable. - * - * @param object $data - * @param array $configs - * @param string $version - * @param string $status - * @access private - * @return array - */ - private function mockConvertDataForDtable($data, $configs, $version, $status) - { - $columns = array(); - $rows = array(); - $cellSpan = array(); - - $headerRow1 = !empty($data->cols[0]) ? $data->cols[0] : array(); - $headerRow2 = !empty($data->cols[1]) ? $data->cols[1] : array(); - - // 模拟列配置生成 - $index = 0; - foreach($headerRow1 as $column) - { - if(!empty($column->colspan) && $column->isSlice && !empty($headerRow2)) - { - $colspan = 0; - while($colspan < $column->colspan) - { - $subColumn = array_shift($headerRow2); - $field = 'field' . $index; - $columns[$field]['name'] = $field; - $columns[$field]['title'] = empty($subColumn->label) ? ' ' : $subColumn->label; - $columns[$field]['headerGroup'] = $column->label; - - if(isset($subColumn->isDrilling) && $subColumn->isDrilling) - { - $columns[$field]['link'] = '#'; - $columns[$field]['drillField'] = $subColumn->drillField; - $columns[$field]['condition'] = $subColumn->condition; - } - - $colspan += $subColumn->colspan ?: 1; - $index++; - } - continue; - } - - $field = 'field' . $index; - $columns[$field]['name'] = $field; - $columns[$field]['title'] = empty($column->label) ? ' ' : $column->label; - - if(isset($column->isDrilling) && $column->isDrilling) - { - $columns[$field]['link'] = '#'; - $columns[$field]['drillField'] = $column->drillField; - $columns[$field]['condition'] = $column->condition; - } - - $index++; - } - - // 模拟行数据生成 - foreach($data->array as $rowKey => $rowData) - { - $index = 0; - foreach($rowData as $value) - { - $field = 'field' . $index; - $rows[$rowKey][$field] = $value; - - // 处理合并单元格配置 - if(isset($configs[$rowKey][$index]) && $configs[$rowKey][$index] > 1) - { - $rows[$rowKey][$field . '_rowspan'] = $configs[$rowKey][$index]; - $cellSpan[$field]['rowspan'] = $field . '_rowspan'; - } - - $index++; - } - - $rows[$rowKey]['conditions'] = array(); - $rows[$rowKey]['isDrill'] = array(); - $rows[$rowKey]['isTotal'] = false; - $rows[$rowKey]['ROW_ID'] = $rowKey; - $rows[$rowKey]['version'] = $version; - $rows[$rowKey]['status'] = $status; - } - - return array($columns, $rows, $cellSpan); - } - - /** - * Test getDrillFields method. - * - * @param int $rowIndex - * @param string $columnKey - * @param array $drills - * @access public - * @return array - */ - public function getDrillFieldsTest(int $rowIndex, string $columnKey, array $drills): array - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->objectModel === null) - { - return $this->mockGetDrillFields($rowIndex, $columnKey, $drills); - } - - try - { - $result = $this->objectModel->getDrillFields($rowIndex, $columnKey, $drills); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟getDrillFields方法的行为 - return $this->mockGetDrillFields($rowIndex, $columnKey, $drills); - } - } - - /** - * Mock getDrillFields method for testing. - * - * @param int $rowIndex - * @param string $columnKey - * @param array $drills - * @access private - * @return array - */ - private function mockGetDrillFields(int $rowIndex, string $columnKey, array $drills): array - { - if(empty($drills) || !isset($drills[$rowIndex]) || !isset($drills[$rowIndex]['drillFields'][$columnKey])) return array(); - - return $drills[$rowIndex]['drillFields'][$columnKey]; - } - - /** - * Test processDrills method. - * - * @param string $field - * @param array $drillFields - * @param array $columns - * @access public - * @return array - */ - public function processDrillsTest(string $field, array $drillFields, array $columns): array - { - $result = $this->objectModel->processDrills($field, $drillFields, $columns); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test prepareDrillConditions method. - * - * @param array $drillFields - * @param array $conditions - * @param string $originField - * @access public - * @return array - */ - public function prepareDrillConditionsTest(array $drillFields, array $conditions, string $originField): array - { - $result = $this->objectModel->prepareDrillConditions($drillFields, $conditions, $originField); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test json2Array method. - * - * @param string|object|array|null $json - * @access public - * @return array - */ - public function json2ArrayTest($json): array - { - // 如果数据库连接失败,直接实现json2Array的逻辑 - if($this->objectModel === null) - { - if(empty($json)) return array(); - if(is_string($json)) return json_decode($json, true); - if(is_object($json)) return json_decode(json_encode($json), true); - return $json; - } - - $result = $this->objectModel->json2Array($json); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test getCorrectGroup method. - * - * @param string $id - * @param string $type - * @access public - * @return string - */ - public function getCorrectGroupTest($id, $type) - { - // 如果模型对象为null(数据库连接失败),使用mock方式 - if($this->objectModel === null) - { - return $this->mockGetCorrectGroup($id, $type); - } - - try - { - $result = $this->objectModel->getCorrectGroup($id, $type); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 当数据库连接失败时,模拟getCorrectGroup方法的行为 - return $this->mockGetCorrectGroup($id, $type); - } - } - - /** - * Mock getCorrectGroup method for testing. - * - * @param string $id - * @param string $type - * @access private - * @return string - */ - private function mockGetCorrectGroup($id, $type) - { - // 处理多个ID的情况 - if(strpos($id, ',') !== false) - { - $ids = explode(',', $id); - $correctIds = array(); - foreach($ids as $singleId) - { - $correctId = $this->mockGetCorrectGroup($singleId, $type); - if($correctId !== '') $correctIds[] = $correctId; - } - return empty($correctIds) ? '' : implode(',', $correctIds); - } - - // 空字符串直接返回空 - if(empty($id)) return ''; - - // 模拟配置数据 - $charts = array( - '32' => array("root" => 1, "name" => "产品", "grade" => 1), - '33' => array("root" => 1, "name" => "项目", "grade" => 1), - '34' => array("root" => 1, "name" => "测试", "grade" => 1), - '35' => array("root" => 1, "name" => "组织", "grade" => 1), - '36' => array("root" => 1, "name" => "需求", "grade" => 2) - ); - - $pivots = array( - '59' => array("root" => 1, "name" => "产品", "grade" => 1), - '60' => array("root" => 1, "name" => "项目", "grade" => 1), - '61' => array("root" => 1, "name" => "测试", "grade" => 1), - '62' => array("root" => 1, "name" => "组织", "grade" => 1) - ); - - $key = "{$type}s"; - $builtinModules = $type == 'chart' ? $charts : $pivots; - - if(!isset($builtinModules[$id])) return ''; - - $builtinModule = $builtinModules[$id]; - - // 模拟数据库查询结果 - 根据配置模拟对应的数据库ID - $moduleMapping = array( - 'chart' => array( - '32' => '1', // 产品,grade=1 -> id=1 - '33' => '2', // 项目,grade=1 -> id=2 - '34' => '3', // 测试,grade=1 -> id=3 - '35' => '4', // 组织,grade=1 -> id=4 - '36' => '5' // 需求,grade=2 -> id=5 - ), - 'pivot' => array( - '59' => '9', // 产品,grade=1 -> id=9 - '60' => '10', // 项目,grade=1 -> id=10 - '61' => '11', // 测试,grade=1 -> id=11 - '62' => '12' // 组织,grade=1 -> id=12 - ) - ); - - return isset($moduleMapping[$type][$id]) ? $moduleMapping[$type][$id] : ''; - } - - /** - * Test downloadDuckdb method. - * - * @access public - * @return string - */ - public function downloadDuckdbTest() - { - $result = $this->objectModel->downloadDuckdb(); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test checkDuckdbInstall method. - * - * @access public - * @return mixed - */ - public function checkDuckdbInstallTest() - { - $result = $this->objectModel->checkDuckdbInstall(); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test updateDownloadingTagFile method. - * - * @param string $type - * @param string $action - * @access public - * @return mixed - */ - public function updateDownloadingTagFileTest($type = 'file', $action = 'create') - { - $result = $this->objectModel->updateDownloadingTagFile($type, $action); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test unzipFile method. - * - * @param string $path - * @param string $file - * @param string $extractFile - * @access public - * @return bool - */ - public function unzipFileTest(string $path, string $file, string $extractFile): bool - { - $result = $this->objectModel->unzipFile($path, $file, $extractFile); - if(dao::isError()) return dao::getError(); - - return $result; - } - - /** - * Test downloadFile method. - * - * @param string $url - * @param string $savePath - * @param string $finalFile - * @access public - * @return mixed - */ - public function downloadFileTest(string $url, string $savePath, string $finalFile) - { - // 由于 downloadFile 方法依赖外部网络资源和文件系统,直接使用 mock 实现进行测试 - return $this->mockDownloadFile($url, $savePath, $finalFile); - } - - /** - * Mock downloadFile method for testing. - * - * @param string $url - * @param string $savePath - * @param string $finalFile - * @access private - * @return bool - */ - private function mockDownloadFile(string $url, string $savePath, string $finalFile): bool - { - // 空参数测试 - if(empty($url) || empty($savePath) || empty($finalFile)) return false; - - // 无效URL测试 - if(!filter_var($url, FILTER_VALIDATE_URL)) return false; - - // 不可达URL测试 - if(strpos($url, 'invalid-domain.test') !== false) return false; - - // 不存在目录测试 - if(strpos($savePath, '/nonexistent/') !== false) return false; - - // 404错误测试 - if(strpos($url, '/status/404') !== false) return false; - - // JSON格式错误测试 - if(strpos($url, '/json-error') !== false) return false; - - // 文件保存失败测试 - if(strpos($savePath, '/readonly/') !== false) return false; - - // ZIP文件测试 - if(strpos($url, '.zip') !== false) return true; - - // 正常下载测试 - if(strpos($url, 'httpbin.org') !== false || strpos($url, 'valid-test') !== false) return true; - - return false; - } - - /** - * Test jsonEncode method. - * - * @param object|array $object - * @access public - * @return mixed - */ - public function jsonEncodeTest($object) - { - $reflection = new ReflectionClass($this->objectModel); - $method = $reflection->getMethod('jsonEncode'); - $method->setAccessible(true); - - $result = $method->invoke($this->objectModel, $object); - if(dao::isError()) return dao::getError(); - - return $result; - } - /** * Test fetchAllTables method. * @@ -3062,51 +16,9 @@ class biTaoTest extends baseTest */ public function fetchAllTablesTest() { - try - { - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('fetchAllTables'); - $method->setAccessible(true); - - $result = $method->invoke($this->instance); - if(dao::isError()) return dao::getError(); - - return $result; - } - catch(Exception $e) - { - // 模拟fetchAllTables的返回结果用于测试 - $mockTables = array(); - - // 排除的表(配置中定义的) - $excludedTables = array('zt_action', 'zt_duckdbqueue', 'zt_metriclib', 'zt_repofiles', 'zt_repohistory', 'zt_queue'); - - // 模拟常见的zentao表 - $allTables = array( - 'zt_user', 'zt_product', 'zt_project', 'zt_story', 'zt_task', 'zt_bug', 'zt_build', - 'zt_testcase', 'zt_testtask', 'zt_testrun', 'zt_testreport', 'zt_doc', 'zt_team', - 'zt_acl', 'zt_group', 'zt_grouppriv', 'zt_usergroup', 'zt_company', 'zt_dept', - 'zt_config', 'zt_cron', 'zt_file', 'zt_history', 'zt_lang', 'zt_module', - 'zt_extension', 'zt_effort', 'zt_burn', 'zt_release', 'zt_branch', 'zt_productplan' - ); - - // 生成足够数量的表以达到239个(排除6个后) - for($i = 1; $i <= 208; $i++) - { - $allTables[] = 'zt_table' . $i; - } - - // 过滤掉排除的表 - foreach($allTables as $table) - { - if(!in_array($table, $excludedTables)) - { - $mockTables[$table] = $table; - } - } - - return $mockTables; - } + $result = $this->invokeArgs('fetchAllTables'); + if(dao::isError()) return dao::getError(); + return $result; } /** @@ -3117,13 +29,8 @@ class biTaoTest extends baseTest */ public function fetchTableQueueTest() { - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('fetchTableQueue'); - $method->setAccessible(true); - - $result = $method->invoke($this->instance); + $result = $this->invokeArgs('fetchTableQueue'); if(dao::isError()) return dao::getError(); - return $result; } @@ -3136,34 +43,15 @@ class biTaoTest extends baseTest */ public function updateSyncTimeTest($tables) { - if(empty($tables)) - { - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('updateSyncTime'); - $method->setAccessible(true); + if(empty($tables)) return 0; - $method->invoke($this->instance, $tables); - if(dao::isError()) return dao::getError(); - - return 0; - } - - global $tester; - $dao = $tester->dao; - - $currentTime = helper::now(); - - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('updateSyncTime'); - $method->setAccessible(true); - - $method->invoke($this->instance, $tables); + $this->invokeArgs('updateSyncTime', [$tables]); if(dao::isError()) return dao::getError(); - $updatedCount = $dao->select('COUNT(*)')->from(TABLE_DUCKDBQUEUE) + $updatedCount = $dao->select('COUNT(1) AS count')->from(TABLE_DUCKDBQUEUE) ->where('object')->in($tables) ->andWhere('syncTime')->ge($currentTime) - ->fetch('COUNT(*)'); + ->fetch('count'); return $updatedCount; } @@ -3176,72 +64,8 @@ class biTaoTest extends baseTest */ public function fetchActionDateTest() { - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('fetchActionDate'); - $method->setAccessible(true); - - $result = $method->invoke($this->instance); + $result = $this->invokeArgs('fetchActionDate'); if(dao::isError()) return dao::getError(); - return $result; } - - /** - * Test fetchActionDate method and return object type. - * - * @access public - * @return string - */ - public function fetchActionDateObjectTest() - { - $reflection = new ReflectionClass($this->instance); - $method = $reflection->getMethod('fetchActionDate'); - $method->setAccessible(true); - - $result = $method->invoke($this->instance); - if(dao::isError()) return dao::getError(); - - return is_object($result) ? 'object' : 'not_object'; - } - - /** - * Mock prepareColumns method for testing. - * - * @param string $sql - * @param object $statement - * @param string $driver - * @access private - * @return array - */ - private function mockPrepareColumns($sql, $statement, $driver = 'mysql') - { - // 模拟getSqlTypeAndFields返回值 - list($columnTypes, $columnFields) = $this->mockGetSqlTypeAndFields($sql, $driver); - - // 模拟getParams4Rebuild返回值 - $fieldPairs = array(); - $relatedObjects = array(); - - foreach($columnFields as $field) - { - $fieldPairs[$field] = ucfirst($field); - $relatedObjects[$field] = 'user'; - } - - // 模拟prepareColumns方法的核心逻辑 - $columns = array(); - $clientLang = 'zh-cn'; - foreach($fieldPairs as $field => $langName) - { - $columns[$field] = array( - 'name' => $field, - 'field' => $field, - 'type' => isset($columnTypes->$field) ? $columnTypes->$field : 'string', - 'object' => $relatedObjects[$field], - $clientLang => $langName - ); - } - - return array($columns, $relatedObjects); - } } diff --git a/module/bi/test/model/gettablefields.php b/module/bi/test/model/gettablefields.php deleted file mode 100755 index a7de72977e..0000000000 --- a/module/bi/test/model/gettablefields.php +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env php -getTableFieldsTest()) && p() && e('array'); // 测试正常调用返回结果是数组类型 -r($bi->getTableFieldsTestNotEmpty()) && p() && e('not_empty'); // 测试返回结果不为空 -r($bi->getTableFieldsTestHasTables()) && p() && e('has_tables'); // 测试返回结果包含表名键 -r($bi->getTableFieldsTestHasFields()) && p() && e('has_fields'); // 测试每个表都包含字段信息 -r($bi->getTableFieldsTestValidStructure()) && p() && e('valid_structure'); // 测试字段信息结构完整性 \ No newline at end of file