Add few APIs to ease tests (#788)

* add few APIs to ease tests

* code style

* log testname via IssueLog only through ItopDataTestCase

* code style

* ci: phpunit fix fatal error
This commit is contained in:
odain-cbd
2025-12-18 13:31:48 +01:00
committed by GitHub
parent f9db405343
commit 6cb08ba361
9 changed files with 139 additions and 139 deletions

View File

@@ -1,10 +1,11 @@
<?php <?php
/* /*
* @copyright Copyright (C) 2010-2023 Combodo SARL * @copyright Copyright (C) 2010-2023 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
*/ */
declare(strict_types = 1); declare(strict_types=1);
/** /**
* This file is only here to allow setting a specific PHP version to run the analysis for without * This file is only here to allow setting a specific PHP version to run the analysis for without
@@ -21,4 +22,4 @@ declare(strict_types = 1);
$config = []; $config = [];
$config['parameters']['phpVersion'] = PHP_VERSION_ID; $config['parameters']['phpVersion'] = PHP_VERSION_ID;
return $config; return $config;

View File

@@ -28,14 +28,14 @@ class AjaxPageTest extends ItopDataTestCase
$iLastCompilation = filemtime(APPROOT.'env-production'); $iLastCompilation = filemtime(APPROOT.'env-production');
// When // When
$sOutput = $this->CallItopUrl( $sOutput = $this->CallItopUri(
"/pages/exec.php?exec_module=itop-hub-connector&exec_page=ajax.php", "pages/exec.php?exec_module=itop-hub-connector&exec_page=ajax.php",
[ [
'auth_user' => $sLogin, 'auth_user' => $sLogin,
'auth_pwd' => self::AUTHENTICATION_PASSWORD, 'auth_pwd' => self::AUTHENTICATION_PASSWORD,
'operation' => "compile", 'operation' => "compile",
'authent' => self::AUTHENTICATION_TOKEN, 'authent' => self::AUTHENTICATION_TOKEN,
] ],
); );
// Then // Then
@@ -53,26 +53,4 @@ class AjaxPageTest extends ItopDataTestCase
clearstatcache(); clearstatcache();
$this->assertGreaterThan($iLastCompilation, filemtime(APPROOT.'env-production'), 'The env-production directory should have been rebuilt'); $this->assertGreaterThan($iLastCompilation, filemtime(APPROOT.'env-production'), 'The env-production directory should have been rebuilt');
} }
protected function CallItopUrl($sUri, ?array $aPostFields = null, bool $bXDebugEnabled = false)
{
$ch = curl_init();
if ($bXDebugEnabled) {
curl_setopt($ch, CURLOPT_COOKIE, 'XDEBUG_SESSION=phpstorm');
}
$sUrl = \MetaModel::GetConfig()->Get('app_root_url')."/$sUri";
var_dump($sUrl);
curl_setopt($ch, CURLOPT_URL, $sUrl);
curl_setopt($ch, CURLOPT_POST, 1);// set post data to true
curl_setopt($ch, CURLOPT_POSTFIELDS, $aPostFields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$sOutput = curl_exec($ch);
//echo "$sUrl error code:".curl_error($ch);
curl_close($ch);
return $sOutput;
}
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* Copyright (C) 2013-2024 Combodo SAS * Copyright (C) 2013-2024 Combodo SAS
* *
@@ -24,19 +25,15 @@
require_once('../../../approot.inc.php'); require_once('../../../approot.inc.php');
require_once(APPROOT.'application/startup.inc.php'); require_once(APPROOT.'application/startup.inc.php');
$sEnvironment = MetaModel::GetEnvironmentId(); $sEnvironment = MetaModel::GetEnvironmentId();
$aEntries = array(); $aEntries = [];
$aCacheUserData = apc_cache_info_compat(); $aCacheUserData = apc_cache_info_compat();
if (is_array($aCacheUserData) && isset($aCacheUserData['cache_list'])) if (is_array($aCacheUserData) && isset($aCacheUserData['cache_list'])) {
{
$sPrefix = 'itop-'.$sEnvironment.'-query-cache-'; $sPrefix = 'itop-'.$sEnvironment.'-query-cache-';
foreach($aCacheUserData['cache_list'] as $i => $aEntry) foreach ($aCacheUserData['cache_list'] as $i => $aEntry) {
{
$sEntryKey = array_key_exists('info', $aEntry) ? $aEntry['info'] : $aEntry['key']; $sEntryKey = array_key_exists('info', $aEntry) ? $aEntry['info'] : $aEntry['key'];
if (strpos($sEntryKey, $sPrefix) === 0) if (strpos($sEntryKey, $sPrefix) === 0) {
{
$aEntries[] = $sEntryKey; $aEntries[] = $sEntryKey;
} }
} }
@@ -44,52 +41,39 @@ if (is_array($aCacheUserData) && isset($aCacheUserData['cache_list']))
echo "<pre>"; echo "<pre>";
if (empty($aEntries)) if (empty($aEntries)) {
{
echo "No Data"; echo "No Data";
return; return;
} }
$sKey = $aEntries[0]; $sKey = $aEntries[0];
$result = apc_fetch($sKey); $result = apc_fetch($sKey);
if (!is_object($result)) if (!is_object($result)) {
{
return; return;
} }
$oSQLQuery = $result; $oSQLQuery = $result;
echo "NB Tables before;NB Tables after;"; echo "NB Tables before;NB Tables after;";
foreach($oSQLQuery->m_aContextData as $sField => $oValue) foreach ($oSQLQuery->m_aContextData as $sField => $oValue) {
{
echo $sField.';'; echo $sField.';';
} }
echo "\n"; echo "\n";
sort($aEntries); sort($aEntries);
foreach($aEntries as $sKey) foreach ($aEntries as $sKey) {
{
$result = apc_fetch($sKey); $result = apc_fetch($sKey);
if (is_object($result)) if (is_object($result)) {
{
$oSQLQuery = $result; $oSQLQuery = $result;
if (isset($oSQLQuery->m_aContextData)) if (isset($oSQLQuery->m_aContextData)) {
{
echo $oSQLQuery->m_iOriginalTableCount.";".$oSQLQuery->CountTables().';'; echo $oSQLQuery->m_iOriginalTableCount.";".$oSQLQuery->CountTables().';';
foreach($oSQLQuery->m_aContextData as $oValue) foreach ($oSQLQuery->m_aContextData as $oValue) {
{ if (is_array($oValue)) {
if (is_array($oValue))
{
$sVal = json_encode($oValue); $sVal = json_encode($oValue);
} } else {
else if (empty($oValue)) {
{
if (empty($oValue))
{
$sVal = ''; $sVal = '';
} } else {
else
{
$sVal = $oValue; $sVal = $oValue;
} }
} }
@@ -101,4 +85,3 @@ foreach($aEntries as $sKey)
} }
echo "</pre>"; echo "</pre>";

View File

@@ -18,6 +18,7 @@ use ArchivedObjectException;
use CMDBObject; use CMDBObject;
use CMDBSource; use CMDBSource;
use Combodo\iTop\Service\Events\EventService; use Combodo\iTop\Service\Events\EventService;
use Config;
use Contact; use Contact;
use DBObject; use DBObject;
use DBObjectSet; use DBObjectSet;
@@ -65,6 +66,9 @@ abstract class ItopDataTestCase extends ItopTestCase
private $aCreatedObjects = []; private $aCreatedObjects = [];
private $aEventListeners = []; private $aEventListeners = [];
protected ?string $sConfigTmpBackupFile = null;
protected ?Config $oiTopConfig = null;
/** /**
* @var bool When testing with silo, there are some cache we need to update on tearDown. Doing it all the time will cost too much, so it's opt-in ! * @var bool When testing with silo, there are some cache we need to update on tearDown. Doing it all the time will cost too much, so it's opt-in !
* @see tearDown * @see tearDown
@@ -119,6 +123,8 @@ abstract class ItopDataTestCase extends ItopTestCase
{ {
parent::setUp(); parent::setUp();
\IssueLog::Error($this->getName());
$this->PrepareEnvironment(); $this->PrepareEnvironment();
if (static::USE_TRANSACTION) { if (static::USE_TRANSACTION) {
@@ -185,6 +191,8 @@ abstract class ItopDataTestCase extends ItopTestCase
CMDBObject::SetCurrentChange(null); CMDBObject::SetCurrentChange(null);
$this->RestoreConfiguration();
parent::tearDown(); parent::tearDown();
} }
@@ -1434,4 +1442,35 @@ abstract class ItopDataTestCase extends ItopTestCase
$oObject->Set($sStopwatchAttCode, $oStopwatch); $oObject->Set($sStopwatchAttCode, $oStopwatch);
} }
protected function BackupConfiguration(): void
{
$sConfigPath = MetaModel::GetConfig()->GetLoadedFile();
clearstatcache();
echo sprintf("rights via ls on %s:\n %s \n", $sConfigPath, exec("ls -al $sConfigPath"));
$sFilePermOutput = substr(sprintf('%o', fileperms('/etc/passwd')), -4);
echo sprintf("rights via fileperms on %s:\n %s \n", $sConfigPath, $sFilePermOutput);
$this->sConfigTmpBackupFile = tempnam(sys_get_temp_dir(), "config_");
MetaModel::GetConfig()->WriteToFile($this->sConfigTmpBackupFile);
$this->oiTopConfig = new Config($sConfigPath);
}
protected function RestoreConfiguration(): void
{
if (is_null($this->sConfigTmpBackupFile) || ! is_file($this->sConfigTmpBackupFile)) {
return;
}
if (is_null($this->oiTopConfig)) {
return;
}
//put config back
$sConfigPath = $this->oiTopConfig->GetLoadedFile();
@chmod($sConfigPath, 0770);
$oConfig = new Config($this->sConfigTmpBackupFile);
$oConfig->WriteToFile($sConfigPath);
@chmod($sConfigPath, 0440);
@unlink($this->sConfigTmpBackupFile);
}
} }

View File

@@ -10,9 +10,9 @@ namespace Combodo\iTop\Test\UnitTest;
use CMDBSource; use CMDBSource;
use DeprecatedCallsLog; use DeprecatedCallsLog;
use MySQLTransactionNotClosedException; use MySQLTransactionNotClosedException;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use ReflectionMethod; use ReflectionMethod;
use SetupUtils; use SetupUtils;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\HttpKernel\KernelInterface;
use const DEBUG_BACKTRACE_IGNORE_ARGS; use const DEBUG_BACKTRACE_IGNORE_ARGS;
@@ -28,6 +28,7 @@ use const DEBUG_BACKTRACE_IGNORE_ARGS;
abstract class ItopTestCase extends KernelTestCase abstract class ItopTestCase extends KernelTestCase
{ {
public const TEST_LOG_DIR = 'test'; public const TEST_LOG_DIR = 'test';
protected array $aFileToClean = [];
/** /**
* @var bool * @var bool
@@ -36,7 +37,7 @@ abstract class ItopTestCase extends KernelTestCase
public const DISABLE_DEPRECATEDCALLSLOG_ERRORHANDLER = true; public const DISABLE_DEPRECATEDCALLSLOG_ERRORHANDLER = true;
public static $DEBUG_UNIT_TEST = false; public static $DEBUG_UNIT_TEST = false;
protected static $aBackupStaticProperties = []; protected static $aBackupStaticProperties = [];
public ?array $aLastCurlGetInfo = null;
/** /**
* @link https://docs.phpunit.de/en/9.6/annotations.html#preserveglobalstate PHPUnit `preserveGlobalState` annotation documentation * @link https://docs.phpunit.de/en/9.6/annotations.html#preserveglobalstate PHPUnit `preserveGlobalState` annotation documentation
* *
@@ -174,6 +175,15 @@ abstract class ItopTestCase extends KernelTestCase
} }
throw new MySQLTransactionNotClosedException('Some DB transactions were opened but not closed ! Fix the code by adding ROLLBACK or COMMIT statements !', []); throw new MySQLTransactionNotClosedException('Some DB transactions were opened but not closed ! Fix the code by adding ROLLBACK or COMMIT statements !', []);
} }
foreach ($this->aFileToClean as $sPath) {
if (is_file($sPath)) {
@unlink($sPath);
continue;
}
SetupUtils::tidydir($sPath);
}
} }
/** /**
@@ -631,4 +641,52 @@ abstract class ItopTestCase extends KernelTestCase
fclose($handle); fclose($handle);
return array_reverse($aLines); return array_reverse($aLines);
} }
/**
* @param $sUrl
* @param array|null $aPostFields
* @param array|null $aCurlOptions
* @param $bXDebugEnabled
* @return string
*/
protected function CallItopUrl($sUrl, ?array $aPostFields = [], ?array $aCurlOptions = [], $bXDebugEnabled = false): string
{
$ch = curl_init();
if ($bXDebugEnabled) {
curl_setopt($ch, CURLOPT_COOKIE, "XDEBUG_SESSION=phpstorm");
}
curl_setopt($ch, CURLOPT_URL, $sUrl);
curl_setopt($ch, CURLOPT_POST, 1);// set post data to true
if (!is_array($aPostFields)) {
var_dump($aPostFields);
}
curl_setopt($ch, CURLOPT_POSTFIELDS, $aPostFields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Force disable of certificate check as most of dev / test env have a self-signed certificate
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
var_dump($aCurlOptions);
curl_setopt_array($ch, $aCurlOptions);
$sOutput = curl_exec($ch);
//\IssueLog::Info("$sUrl error code:", null, ['error' => curl_error($ch)]);
$info = curl_getinfo($ch);
$this->aLastCurlGetInfo = $info;
$sErrorMsg = curl_error($ch);
$iErrorCode = curl_errno($ch);
curl_close($ch);
\IssueLog::Info(__METHOD__, null, ['url' => $sUrl, 'error' => $sErrorMsg, 'error_code' => $iErrorCode, 'post_fields' => $aPostFields, 'info' => $info]);
return $sOutput;
}
protected function CallItopUri(string $sUri, ?array $aPostFields = [], ?array $aCurlOptions = [], $bXDebugEnabled = false): string
{
$sUrl = \MetaModel::GetConfig()->Get('app_root_url')."/$sUri";
return $this->CallItopUrl($sUrl, $aPostFields, $aCurlOptions, $bXDebugEnabled);
}
} }

View File

@@ -7,7 +7,6 @@ use MetaModel;
class LoginTest extends ItopDataTestCase class LoginTest extends ItopDataTestCase
{ {
protected $sConfigTmpBackupFile;
protected $sConfigPath; protected $sConfigPath;
protected $sLoginMode; protected $sLoginMode;

View File

@@ -172,34 +172,11 @@ class QueryTest extends ItopDataTestCase
{ {
// compute request url // compute request url
$url = $oQuery->GetExportUrl(); $url = $oQuery->GetExportUrl();
$aCurlOptions = [
// open curl CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
$curl = curl_init(); CURLOPT_USERPWD => self::USER.':'.self::PASSWORD,
];
// curl options return $this->CallItopUrl($url, [], $aCurlOptions);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($curl, CURLOPT_USERPWD, self::USER.':'.self::PASSWORD);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
// Force disable of certificate check as most of dev / test env have a self-signed certificate
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
// execute curl
$result = curl_exec($curl);
if (curl_errno($curl)) {
$info = curl_getinfo($curl);
var_export($info);
var_dump([
'url' => $url,
'app_root_url:' => MetaModel::GetConfig()->Get('app_root_url'),
'GetAbsoluteUrlAppRoot:' => \utils::GetAbsoluteUrlAppRoot(),
]);
}
// close curl
curl_close($curl);
return $result;
} }
/** @inheritDoc */ /** @inheritDoc */

View File

@@ -12,10 +12,8 @@ class CliResetSessionTest extends ItopDataTestCase
public const USE_TRANSACTION = false; public const USE_TRANSACTION = false;
private $sCookieFile = ""; private $sCookieFile = "";
private $sUrl;
private $sLogin; private $sLogin;
private $sPassword = "Iuytrez9876543ç_è-("; private $sPassword = "Iuytrez9876543ç_è-(";
protected $sConfigTmpBackupFile;
/** /**
* @throws Exception * @throws Exception
@@ -24,16 +22,13 @@ class CliResetSessionTest extends ItopDataTestCase
{ {
parent::setUp(); parent::setUp();
$this->sConfigTmpBackupFile = tempnam(sys_get_temp_dir(), "config_"); $this->BackupConfiguration();
MetaModel::GetConfig()->WriteToFile($this->sConfigTmpBackupFile);
$this->sLogin = "rest-user-".date('dmYHis'); $this->sLogin = "rest-user-".date('dmYHis');
$this->CreateTestOrganization(); $this->CreateTestOrganization();
$this->sCookieFile = tempnam(sys_get_temp_dir(), 'jsondata_'); $this->sCookieFile = tempnam(sys_get_temp_dir(), 'jsondata_');
$this->sUrl = \MetaModel::GetConfig()->Get('app_root_url');
$oRestProfile = \MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", ['name' => 'REST Services User'], true); $oRestProfile = \MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", ['name' => 'REST Services User'], true);
$oAdminProfile = \MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", ['name' => 'Administrator'], true); $oAdminProfile = \MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", ['name' => 'Administrator'], true);
@@ -47,16 +42,6 @@ class CliResetSessionTest extends ItopDataTestCase
{ {
parent::tearDown(); parent::tearDown();
if (! is_null($this->sConfigTmpBackupFile) && is_file($this->sConfigTmpBackupFile)) {
//put config back
$sConfigPath = MetaModel::GetConfig()->GetLoadedFile();
@chmod($sConfigPath, 0770);
$oConfig = new Config($this->sConfigTmpBackupFile);
$oConfig->WriteToFile($sConfigPath);
@chmod($sConfigPath, 0444);
unlink($this->sConfigTmpBackupFile);
}
if (!empty($this->sCookieFile)) { if (!empty($this->sCookieFile)) {
unlink($this->sCookieFile); unlink($this->sCookieFile);
} }
@@ -150,26 +135,18 @@ class CliResetSessionTest extends ItopDataTestCase
*/ */
private function SendHTTPRequestWithCookies($sUri, $aPostFields, $sForcedLoginMode = null): string private function SendHTTPRequestWithCookies($sUri, $aPostFields, $sForcedLoginMode = null): string
{ {
$ch = curl_init();
curl_setopt($ch, CURLOPT_COOKIEJAR, $this->sCookieFile);
curl_setopt($ch, CURLOPT_COOKIEFILE, $this->sCookieFile);
$sUrl = "$this->sUrl/$sUri";
if (!is_null($sForcedLoginMode)) { if (!is_null($sForcedLoginMode)) {
$sUrl .= "?login_mode=$sForcedLoginMode"; $sUri .= "?login_mode=$sForcedLoginMode";
} }
curl_setopt($ch, CURLOPT_URL, $sUrl);
curl_setopt($ch, CURLOPT_POST, 1);// set post data to true
curl_setopt($ch, CURLOPT_POSTFIELDS, $aPostFields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
// Force disable of certificate check as most of dev / test env have a self-signed certificate
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$sResponse = curl_exec($ch); $aCurlOptions = [
CURLOPT_COOKIEJAR => $this->sCookieFile,
CURLOPT_COOKIEFILE => $this->sCookieFile,
CURLOPT_HEADER => 1,
];
$sResponse = $this->CallItopUri($sUri, $aPostFields, $aCurlOptions);
var_dump($this->aLastCurlGetInfo);
/** $sResponse example /** $sResponse example
* "HTTP/1.1 200 OK * "HTTP/1.1 200 OK
Date: Wed, 07 Jun 2023 05:00:40 GMT Date: Wed, 07 Jun 2023 05:00:40 GMT
@@ -177,16 +154,15 @@ class CliResetSessionTest extends ItopDataTestCase
Set-Cookie: itop-2e83d2e9b00e354fdc528621cac532ac=q7ldcjq0rvbn33ccr9q8u8e953; path=/ Set-Cookie: itop-2e83d2e9b00e354fdc528621cac532ac=q7ldcjq0rvbn33ccr9q8u8e953; path=/
*/ */
//var_dump($sResponse); //var_dump($sResponse);
$iHeaderSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $iHeaderSize = $this->aLastCurlGetInfo['header_size'] ?? 0;
$sBody = substr($sResponse, $iHeaderSize); $sBody = substr($sResponse, $iHeaderSize);
//$iHttpCode = intval(curl_getinfo($ch, CURLINFO_HTTP_CODE)); //$iHttpCode = intval(curl_getinfo($ch, CURLINFO_HTTP_CODE));
if (preg_match('/HTTP.* (\d*) /', $sResponse, $aMatches)) { if (preg_match('/HTTP.* (\d*) /', $sResponse, $aMatches)) {
$sHttpCode = $aMatches[1]; $sHttpCode = $aMatches[1];
} else { } else {
$sHttpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $sHttpCode = $this->aLastCurlGetInfo['http_code'] ?? -1;
} }
curl_close($ch);
$this->assertEquals(200, $sHttpCode, "The test logic assumes that the HTTP request is correctly handled"); $this->assertEquals(200, $sHttpCode, "The test logic assumes that the HTTP request is correctly handled");
return $sBody; return $sBody;

View File

@@ -17,7 +17,6 @@ class RestTest extends ItopDataTestCase
public const USE_TRANSACTION = false; public const USE_TRANSACTION = false;
public const CREATE_TEST_ORG = false; public const CREATE_TEST_ORG = false;
private static $sUrl;
private static $sLogin; private static $sLogin;
private static $sPassword = "Iuytrez9876543ç_è-("; private static $sPassword = "Iuytrez9876543ç_è-(";
@@ -44,7 +43,6 @@ class RestTest extends ItopDataTestCase
{ {
parent::setUp(); parent::setUp();
static::$sUrl = MetaModel::GetConfig()->Get('app_root_url');
static::$sLogin = "rest-user-".date('dmYHis'); static::$sLogin = "rest-user-".date('dmYHis');
$this->CreateTestOrganization(); $this->CreateTestOrganization();
@@ -297,16 +295,7 @@ JSON;
$aPostFields['callback'] = $sCallbackName; $aPostFields['callback'] = $sCallbackName;
} }
curl_setopt($ch, CURLOPT_URL, static::$sUrl."/webservices/rest.php"); $sJson = $this->CallItopUri('webservices/rest.php', $aPostFields);
curl_setopt($ch, CURLOPT_POST, 1);// set post data to true
curl_setopt($ch, CURLOPT_POSTFIELDS, $aPostFields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Force disable of certificate check as most of dev / test env have a self-signed certificate
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$sJson = curl_exec($ch);
curl_close($ch);
if (!is_null($sTmpFile)) { if (!is_null($sTmpFile)) {
unlink($sTmpFile); unlink($sTmpFile);