Merge remote-tracking branch 'origin/master' into workflow_support

# Conflicts:
#	pom.xml
This commit is contained in:
HuangXin 2025-03-14 17:50:57 +08:00
commit e211ab25d3
22 changed files with 591 additions and 118 deletions

65
assembly.xml Normal file
View File

@ -0,0 +1,65 @@
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 https://maven.apache.org/xsd/assembly-2.2.0.xsd">
<id>${project.version}</id>
<formats>
<format>tgz</format>
</formats>
<fileSets>
<fileSet>
<directory>./target/</directory>
<includes>
<include>MiddlewareAgent.jar</include>
</includes>
<outputDirectory>${file.separator}</outputDirectory>
</fileSet>
<fileSet>
<directory>./config</directory>
<outputDirectory>${file.separator}config</outputDirectory>
</fileSet>
<fileSet>
<directory>./bin</directory>
<outputDirectory>${file.separator}bin</outputDirectory>
</fileSet>
<fileSet>
<directory>../</directory>
<outputDirectory>${file.separator}</outputDirectory>
<includes>
<include>../CHANGELOG.md</include>
<include>../README.md</include>
</includes>
</fileSet>
<fileSet>
<directory>src/main/resources/</directory>
<includes>
<include>**/*</include>
<include>*</include>
</includes>
<excludes>
<exclude>**/git.properties</exclude>
<exclude>**/smart-doc.json</exclude>
<exclude>**/db/**</exclude>
</excludes>
<outputDirectory>${file.separator}</outputDirectory>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<unpack>false</unpack>
<useProjectArtifact>true</useProjectArtifact>
<outputDirectory>lib</outputDirectory>
<scope>provided</scope>
</dependencySet>
<dependencySet>
<unpack>false</unpack>
<useProjectArtifact>true</useProjectArtifact>
<outputDirectory>lib</outputDirectory>
<scope>system</scope>
</dependencySet>
<dependencySet>
<unpack>false</unpack>
<useProjectArtifact>true</useProjectArtifact>
<outputDirectory>lib</outputDirectory>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
</assembly>

8
bin/start.sh Normal file
View File

@ -0,0 +1,8 @@
#!/bin/bash
JAVA_DEBUG_OPTS=" -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=8001,server=y,suspend=n "
JAVA_JMX_OPTS=" -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false "
JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom -server -Xms512M -Xmx512M -Xss256K -XX:MetaspaceSize=16M -XX:MaxMetaspaceSize=128M -XX:MaxDirectMemorySize=1g -XX:SurvivorRatio=8 -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof"
WORK_PATH=$(cd `dirname $0`; pwd)
cd $WORK_PATH
cd ..
$JAVA_HOME/bin/java $JAVA_DEBUG_OPTS $JAVA_JMX_OPTS $JAVA_OPTS -jar MiddlewareAgent.jar &

15
bin/stop.sh Normal file
View File

@ -0,0 +1,15 @@
#!/bin/bash
APP_NAME=CommonFramework-exec
pids=`ps -ef | grep $APP_NAME | grep -v grep | awk '{print $2}'`
for pid in $pids
do
echo stop $APP_NAME java process: $pid
kill -9 $pid
done
nr_pids=`ps -ef | grep $APP_NAME | grep -v grep | wc -l`
while [ $nr_pids -gt 0 ]
do
nr_pids=`ps -ef | grep $APP_NAME | grep -v grep | wc -l`
done

View File

@ -1,7 +1,9 @@
package com.cmcc.magent;
import com.cmcc.hy.gzs.common.sign.autoconfigure.EnableSign;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
@ -28,6 +30,8 @@ import org.springframework.scheduling.annotation.EnableScheduling;
*/
@SpringBootApplication
@EnableScheduling
@EnableFeignClients
@EnableSign
public class MiddlewareAgentApplication {
/**

View File

@ -190,7 +190,7 @@ public class CommonConfigure {
log.error("Unable get local ip address: {}", e.getMessage());
} finally {
setGlobalVars(serverProperties.getServlet().getContextPath(),
"http://" + addr + ":" + serverProperties.getPort() + serverProperties.getServlet().getContextPath(),
"https://" + addr + ":" + serverProperties.getPort() + serverProperties.getServlet().getContextPath(),
addr,
serverProperties.getPort());
log.info("baseUrl: {}", BASEURL);

View File

@ -0,0 +1,38 @@
package com.cmcc.magent.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
/**
* MwCoreConfig类用于配置与中间件核心相关的属性
*
* <p>该类包含客户端ID和客户端密钥用于与GZS服务进行身份验证</p>
*
* <p>该配置类会在Spring容器启动时加载并支持动态刷新配置</p>
*
* @author huangxin@cmhi.chinamobile.com
* @version 1.0.0
* @since 2025-03-07
*/
@Component
@RefreshScope
@ConfigurationProperties(prefix = "mw.agent")
@Data
public class MwCoreConfig {
/**
* 内部客户端ID
*
* <p>默认为"mw-open-82hsbmz8"可通过配置文件进行覆盖</p>
*/
private String innerClientId = "mw-open-82hsbmz8";
/**
* 内部客户端密钥
*
* <p>默认为"98rnk8pz6j08fp6q"可通过配置文件进行覆盖</p>
*/
private String innerClientSecret = "98rnk8pz6j08fp6q";
}

View File

@ -0,0 +1,40 @@
package com.cmcc.magent.interceptor;
import com.cmcc.hy.gzs.common.feign.GzsSignRequestInterceptor;
import com.cmcc.magent.config.MwCoreConfig;
import lombok.RequiredArgsConstructor;
/**
* MwSignRequestInterceptor类实现了GzsSignRequestInterceptor接口
*
* <p>该类用于拦截请求并提供客户端ID和客户端密钥用于与GZS服务的身份验证</p>
*
* @author huangxin@cmhi.chinamobile.com
* @version 1.0.0
* @since 2025-03-07
*/
@RequiredArgsConstructor
public class MwSignRequestInterceptor implements GzsSignRequestInterceptor {
private final MwCoreConfig mwCoreProperties;
/**
* 获取客户端ID
*
* @return 客户端ID
*/
@Override
public String getClientId() {
return mwCoreProperties.getInnerClientId();
}
/**
* 获取客户端密钥
*
* @return 客户端密钥
*/
@Override
public String getClientSecret() {
return mwCoreProperties.getInnerClientSecret();
}
}

View File

@ -2,7 +2,6 @@ package com.cmcc.magent.pojo.dto;
import com.cmcc.magent.pojo.po.RemoteFileDetails;
import com.cmcc.magent.validation.group.ValidGroups;
import com.cmcc.magent.validation.valids.ValidFixValues;
import com.fasterxml.jackson.annotation.JsonInclude;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
@ -34,7 +33,6 @@ public class DeployMiddlewareFileReq {
* 中间件类型不能为空并且必须是指定的固定值之一Redis, Nginx, Keepalived
*/
@NotBlank(message = "middleware Not Blank", groups = {ValidGroups.MiddlewareDeploymentReqValid.class})
@ValidFixValues(value = {"Redis", "Nginx", "Keepalived"}, ignoreSwitchCase = true, groups = {ValidGroups.MiddlewareDeploymentReqValid.class})
private String middleware;
/**

View File

@ -2,7 +2,6 @@ package com.cmcc.magent.pojo.dto;
import com.cmcc.magent.pojo.po.RemoteFileDetails;
import com.cmcc.magent.validation.group.ValidGroups;
import com.cmcc.magent.validation.valids.ValidFixValues;
import com.fasterxml.jackson.annotation.JsonInclude;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
@ -34,7 +33,6 @@ public class DeploymentMiddlewareReq {
* 中间件类型不能为空并且必须是指定的固定值之一Redis, Nginx, Keepalived
*/
@NotBlank(message = "middleware Not Blank", groups = {ValidGroups.MiddlewareDeploymentReqValid.class})
@ValidFixValues(value = {"Redis", "Nginx", "Keepalived"}, ignoreSwitchCase = true, groups = {ValidGroups.MiddlewareDeploymentReqValid.class})
private String middleware;
/**

View File

@ -0,0 +1,52 @@
package com.cmcc.magent.service;
import com.cmcc.hy.gzs.common.result.Result;
import com.cmcc.magent.interceptor.MwSignRequestInterceptor;
import com.cmcc.magent.pojo.po.RegisterAgent;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
/**
* PlatformApiFeignClientService 接口定义了与平台 API 通信的核心服务功能
* <p>
* 该接口包含与平台交互的关键操作具体实现类负责与平台进行数据交互
* </p>
*
* @author huangxin@cmhi.chinamobile.com
* @version 1.0.0
* @since 2025-03-10
*/
@FeignClient(name = "agent-portal-feign",
url = "${service.platform-url}",
path = "/mw/core",
configuration = MwSignRequestInterceptor.class)
public interface PlatformApiFeignClientService {
/**
* 注册代理
*
* @param agent 要注册的代理信息包含代理的相关属性
* @return 返回一个 {@link Result} 对象包含注册结果的状态和消息
*/
@PostMapping(path = "/register", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
Result<String> registerAgentFeign(@RequestBody RegisterAgent agent);
/**
* 响应部署结果
*
* <p>该方法用于更新指定部署的状态服务器将根据传入的状态信息进行相应处理</p>
*
* @param deploymentId 部署的唯一标识符用于指定需要更新状态的部署
* @param status 部署状态整数类型表示当前部署的状态如成功失败等
* @return 返回一个 {@link Result} 对象包含操作结果的状态和相关信息
*
*/
@PostMapping(path = "/innerapi/instance/update-status",
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
Result<String> responseDeploymentResultFeign(@RequestParam("deploymentId") String deploymentId, @RequestParam("status") Integer status);
}

View File

@ -1,8 +1,8 @@
package com.cmcc.magent.service;
import com.cmcc.hy.gzs.common.result.Result;
import com.cmcc.magent.pojo.po.RegisterAgent;
import java.io.IOException;
import org.springframework.web.bind.annotation.RequestBody;
/**
* PlatformApiService 接口定义了与平台 API 通信的核心服务功能
@ -15,16 +15,23 @@ import java.io.IOException;
* @since 2025-01-07
*/
public interface PlatformApiService {
/**
* 注册代理
*
* @param agent 要注册的代理信息包含代理的相关属性
* @return 返回一个 {@link Result} 对象包含注册结果的状态和消息
*/
Result<String> registerAgent(@RequestBody RegisterAgent agent);
/**
* 注册代理Agent
* <p>
* 该方法用于将代理实例注册到平台并返回平台生成的响应结果
* </p>
* 响应部署结果
*
* <p>该方法用于更新指定部署的状态服务器将根据传入的状态信息进行相应处理</p>
*
* @param deploymentId 部署的唯一标识符用于指定需要更新状态的部署
* @param status 部署状态整数类型表示当前部署的状态如成功失败等
* @return 返回一个 {@link Result} 对象包含操作结果的状态和相关信息
*
* @param agent 包含代理注册信息的 {@link RegisterAgent} 对象
* @return 平台返回的结果通常为一个 JSON 格式的字符串
* @throws IOException 如果在处理 JSON 时发生错误
*/
String registerAgent(RegisterAgent agent) throws IOException;
Result<String> responseDeploymentResult(String deploymentId, Integer status);
}

View File

@ -16,6 +16,7 @@ import com.cmcc.magent.pojo.po.LocalShellContext;
import com.cmcc.magent.pojo.po.RemoteFileContext;
import com.cmcc.magent.pojo.po.RemoteFileDetails;
import com.cmcc.magent.service.MiddlewareManagerService;
import com.cmcc.magent.service.PlatformApiService;
import com.fasterxml.jackson.core.JsonProcessingException;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
@ -64,6 +65,9 @@ public class MiddlewareManagerServiceImpl implements MiddlewareManagerService {
@Resource
private OssFactory ossFactory;
@Resource
private PlatformApiService platformApiService;
/**
* 根据命令获取对应的文件名
*
@ -363,6 +367,13 @@ public class MiddlewareManagerServiceImpl implements MiddlewareManagerService {
}
runCommand(workDir, command);
log.info("---- Task {} Finished", data.getUid());
}).whenComplete((v, t) -> {
if (t != null) {
platformApiService.responseDeploymentResult(data.getUid(), 2);
log.error("---- Task {} Finished With Exception: {}", data.getUid(), t.getMessage());
} else {
log.info("---- Task {} Finished: {}", data.getUid(), platformApiService.responseDeploymentResult(data.getUid(), 1));
}
});
}
@ -440,6 +451,13 @@ public class MiddlewareManagerServiceImpl implements MiddlewareManagerService {
runCommand(workDir, cmd);
log.info("---- Task {} Finished", data.getUid());
}).whenComplete((v, t) -> {
if (t != null) {
platformApiService.responseDeploymentResult(data.getUid(), 2);
log.error("---- Task {} Finished With Exception: {}", data.getUid(), t.getMessage());
} else {
log.info("---- Task {} Finished: {}", data.getUid(), platformApiService.responseDeploymentResult(data.getUid(), 1));
}
});
}

View File

@ -1,17 +1,15 @@
package com.cmcc.magent.service.impl;
import com.cmcc.magent.config.PlatformServiceConfig;
import com.cmcc.magent.misc.HttpClientUtils;
import com.cmcc.magent.misc.JsonUtils;
import com.cmcc.hy.gzs.common.result.Result;
import com.cmcc.magent.pojo.po.RegisterAgent;
import com.cmcc.magent.service.PlatformApiFeignClientService;
import com.cmcc.magent.service.PlatformApiService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.io.IOException;
/**
* PlatformApiServiceImpl {@link PlatformApiService} 的具体实现类
* PlatformApiServiceImpl {@link PlatformApiFeignClientService} 的具体实现类
* <p>
* 该类使用 与平台 API 进行交互提供了注册代理的功能
* </p>
@ -26,24 +24,50 @@ import java.io.IOException;
* @since 2025 -01-07
*/
@Service
@Slf4j
public class PlatformApiServiceImpl implements PlatformApiService {
@Resource
private PlatformServiceConfig platformServiceConfig;
private PlatformApiFeignClientService platformApiServiceFeign;
/**
* 注册代理Agent
* <p>
* 通过向平台 API 提供的注册接口"/register"发送 POST 请求完成代理的注册操作
* 请求体为转换为 JSON 格式的 {@link RegisterAgent} 对象
* </p>
* 注册代理
*
* @param agent 包含代理注册信息的 {@link RegisterAgent} 实例
* @return 平台返回的注册结果通常为 JSON 格式的字符串
* @throws IOException IO 异常
* @param agent 要注册的代理信息包含代理的相关属性
* @return 返回一个 {@link Result} 对象包含注册结果的状态和消息
*/
@Override
public String registerAgent(RegisterAgent agent) throws IOException {
String reqString = JsonUtils.getJson(agent);
return HttpClientUtils.postJson(platformServiceConfig + "/register", null, reqString, null);
public Result<String> registerAgent(RegisterAgent agent) {
Result<String> s = null;
try {
s = platformApiServiceFeign.registerAgentFeign(agent);
} catch (Exception e) {
log.error("Register agent client {} exception: {}", agent.getDeviceId(), e.getMessage());
}
return s;
}
/**
* 响应部署结果
*
* <p>该方法用于更新指定部署的状态服务器将根据传入的状态信息进行相应处理</p>
*
* @param deploymentId 部署的唯一标识符用于指定需要更新状态的部署
* @param status 部署状态整数类型表示当前部署的状态如成功失败等
* @return 返回一个 {@link Result} 对象包含操作结果的状态和相关信息
*
*/
@Override
public Result<String> responseDeploymentResult(String deploymentId, Integer status) {
Result<String> s = null;
try {
s = platformApiServiceFeign.responseDeploymentResultFeign(deploymentId, status);
} catch (Exception e) {
log.error("Response deployment {} result exception: {}", deploymentId, e.getMessage());
}
return s;
}
}

View File

@ -5,6 +5,16 @@ server.compression.enabled=true
server.compression.mime-types=application/json
server.compression.min-response-size=1KB
server.ssl.key-store-type=PKCS12
server.ssl.key-store=classpath:certs/keystore.p12
server.ssl.key-store-password=101010
server.ssl.key-alias=tomcat
server.undertow.buffer-size=1024
server.undertow.max-http-post-size=10MB
# Spring Web Configuration
spring.web.resources.add-mappings=false
@ -70,7 +80,7 @@ protocol.crypto-type=0
# Platform Service
# Manager Platform URL
service.platform-url=http://xajhuang.com:1300
service.platform-url=https://172.21.44.35:50443/mw/core
# APPID
service.platform-appid=appid
# cluster name
@ -84,3 +94,21 @@ thread.max-pool-size=10
thread.queue-capacity=25
thread.name-prefix=Async-
# Can support profiles, databases, or remote
gzs.sign.client-details-enabled=true
gzs.sign.client-details.'mw-open-82hsbmz8'=98rnk8pz6j08fp6q
# Permission: Specifies the interface corresponding to client_id. If the default value is empty, there is no restriction.
#gzs.sign.perm.'yj-yy-1234567'=/xx/xx,/xx/yy
# default can be configured in the rule-group, for example, gzs.sign.rule-.yj.mode =0
# [Optional] 1: strict mode, 0: common mode (default)
#gzs.sign.rule.default.mode=0
# [Optional] Mandatory check list (In any mode, the following interfaces require check)
gzs.sign.rule.default.required-list=POST:/xxx/xx,*:/xxx/yy/**
# [Optional] Optional check list (In any mode, the following interfaces can be checked)
#gzs.sign.rule.default.optional-list=GET:/xxx/xx,*:/xxx/yy/*
# [Optional] If base64 encoding is used, you can configure whether base64 encoding for url security is required in the signature algorithm based on different client_id. The default value is true
#gzs.sign.base64-url-safe.def = true
#gzs.sign.base64-url-safe.'as-xx-1234567' = false

View File

@ -0,0 +1,119 @@
-----BEGIN CERTIFICATE-----
MIIG/zCCBeegAwIBAgIIUPS1tguj0LAwDQYJKoZIhvcNAQELBQAwgbQxCzAJBgNV
BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRow
GAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjEtMCsGA1UECxMkaHR0cDovL2NlcnRz
LmdvZGFkZHkuY29tL3JlcG9zaXRvcnkvMTMwMQYDVQQDEypHbyBEYWRkeSBTZWN1
cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIwHhcNMjMwNjA4MDc0ODQ5WhcN
MjQwNzA5MDc0ODQ5WjCBgTELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCea1meaxn+ec
gTESMBAGA1UEBwwJ5p2t5bee5biCMTMwMQYDVQQKDCrkuK3np7vvvIjmna3lt57v
vInkv6Hmga/mioDmnK/mnInpmZDlhazlj7gxFTATBgNVBAMMDCoua29tZWN0LmNv
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALgQ3fh8pvHAn7NCkZxJ
q1VygM8DWR7qCZS55bMqaqceFdrly+bB+80WKfddXncD1pUKQ77SNsEZyC1DT+Ei
mOro8GITVl/iuZc6QtDM/ZeXnKDSrvxGL7j5EvOUYYAG1WEvZLzNptImWFoAZFF7
h9+HmyZGWiEsCaDrunGNCJpwtborMkH8om6usa3SNaAdM9eKVzrX6yEc+AN3FcoY
/HQxz9rV7b3E4xjVoAkJRyuzihb0ITyYabFYuLI6u4UIlOEhf0SCr7W4KCKepuwS
Lg2MzVRiiuIRgZUqIzI8Oi5ta51mDYoaPxCz1bHiNCKvXqKdAMj6EePFtEkYgw2k
5lMCAwEAAaOCA0QwggNAMAwGA1UdEwEB/wQCMAAwKQYDVR0lBCIwIAYIKwYBBQUH
AwEGCCsGAQUFBwMCBgpghkgBhvhNAQIDMA4GA1UdDwEB/wQEAwIFoDA2BgNVHR8E
LzAtMCugKaAnhiVodHRwOi8vY3JsLmdvZGFkZHkuY29tL2dkaWcyczItMzQuY3Js
MF0GA1UdIARWMFQwSAYLYIZIAYb9bQEHFwIwOTA3BggrBgEFBQcCARYraHR0cDov
L2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzAIBgZngQwBAgIw
dgYIKwYBBQUHAQEEajBoMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5nb2RhZGR5
LmNvbS8wQAYIKwYBBQUHMAKGNGh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j
b20vcmVwb3NpdG9yeS9nZGlnMi5jcnQwHwYDVR0jBBgwFoAUQMK9J47MNIMwojPX
+2yz8LQsgM4wIwYDVR0RBBwwGoIMKi5rb21lY3QuY29tggprb21lY3QuY29tMB0G
A1UdDgQWBBQFlcp3bINcQRB28YU7+JkTZNny0jCCAX8GCisGAQQB1nkCBAIEggFv
BIIBawFpAHYA7s3QZNXbGs7FXLedtM0TojKHRny87N7DUUhZRnEftZsAAAGImfrM
PQAABAMARzBFAiEAwa+pHvLsodr6zaIJHpuep/5KHQtFWdq5xjPxkRYimQACICag
BJw5onUWGDUuw4VDmO1baenKnAG+KdDcDHBdnySIAHYASLDja9qmRzQP5WoC+p0w
6xxSActW3SyB2bu/qznYhHMAAAGImfrNEQAABAMARzBFAiEAv+fe4tG+BSqZ3yeT
NbBDVtfvEMqxrTmAffGO+qT8Zr8CIAIjfZVueI2UAZdrShrRlzZZLK2Npd/t0i6o
4BIaw1o5AHcA2ra/az+1tiKfm8K7XGvocJFxbLtRhIU0vaQ9MEjX+6sAAAGImfrN
dAAABAMASDBGAiEA73dx8CnNv0WGtgByp+Uz3dLspndGI3hu1NOvMtjCCxMCIQD7
BoJJe9knyxpvEOPY+O5ybWj/0HIirHxwJu+qpwp6ZzANBgkqhkiG9w0BAQsFAAOC
AQEABTskU6npLQQx5MUhAhoxH+nu+nz42E3A1vqljjHSey25QLtYKZG+7Zy4g9rZ
Lu09+/byhUL4VSYXaVbuxkwCu2DRnDH34C31Ons3JN5biE/kAqaXA0e+84sUGoot
UtDTe11F1bWwPO3/WYXICGO+GaukUwI4EZP69n6aROMS4+bXiYDqVqbcjq2v9yoq
JoOAkQOSg9fEYkz/oO/xqkTEK1uNjWErWiDW3vuWaXfya2lyRQYasfuryKSNBzhJ
W9tqNooO7Y1kbVSRrZ44kWyBWn0bVQGKzmHeckFP7rkYQi/g34UorHvMUUcJkaLE
p3lPKExQ4l0G4+CNqI2ZawgBrg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIE0DCCA7igAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTExMDUwMzA3MDAwMFoXDTMxMDUwMzA3
MDAwMFowgbQxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjEtMCsGA1UE
CxMkaHR0cDovL2NlcnRzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkvMTMwMQYDVQQD
EypHbyBEYWRkeSBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC54MsQ1K92vdSTYuswZLiBCGzD
BNliF44v/z5lz4/OYuY8UhzaFkVLVat4a2ODYpDOD2lsmcgaFItMzEUz6ojcnqOv
K/6AYZ15V8TPLvQ/MDxdR/yaFrzDN5ZBUY4RS1T4KL7QjL7wMDge87Am+GZHY23e
cSZHjzhHU9FGHbTj3ADqRay9vHHZqm8A29vNMDp5T19MR/gd71vCxJ1gO7GyQ5HY
pDNO6rPWJ0+tJYqlxvTV0KaudAVkV4i1RFXULSo6Pvi4vekyCgKUZMQWOlDxSq7n
eTOvDCAHf+jfBDnCaQJsY1L6d8EbyHSHyLmTGFBUNUtpTrw700kuH9zB0lL7AgMB
AAGjggEaMIIBFjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV
HQ4EFgQUQMK9J47MNIMwojPX+2yz8LQsgM4wHwYDVR0jBBgwFoAUOpqFBxBnKLbv
9r0FQW4gwZTaD94wNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8v
b2NzcC5nb2RhZGR5LmNvbS8wNQYDVR0fBC4wLDAqoCigJoYkaHR0cDovL2NybC5n
b2RhZGR5LmNvbS9nZHJvb3QtZzIuY3JsMEYGA1UdIAQ/MD0wOwYEVR0gADAzMDEG
CCsGAQUFBwIBFiVodHRwczovL2NlcnRzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkv
MA0GCSqGSIb3DQEBCwUAA4IBAQAIfmyTEMg4uJapkEv/oV9PBO9sPpyIBslQj6Zz
91cxG7685C/b+LrTW+C05+Z5Yg4MotdqY3MxtfWoSKQ7CC2iXZDXtHwlTxFWMMS2
RJ17LJ3lXubvDGGqv+QqG+6EnriDfcFDzkSnE3ANkR/0yBOtg2DZ2HKocyQetawi
DsoXiWJYRBuriSUBAA/NxBti21G00w9RKpv0vHP8ds42pM3Z2Czqrpv1KrKQ0U11
GIo/ikGQI31bS/6kA1ibRrLDYGCD+H1QQc7CoZDDu+8CL9IVVO5EFdkKrqeKM+2x
LXY2JtwE65/3YR8V3Idv7kaWKK2hJn0KCacuBKONvPi8BDAB
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEfTCCA2WgAwIBAgIDG+cVMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVT
MSEwHwYDVQQKExhUaGUgR28gRGFkZHkgR3JvdXAsIEluYy4xMTAvBgNVBAsTKEdv
IERhZGR5IENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQwMTAx
MDcwMDAwWhcNMzEwNTMwMDcwMDAwWjCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHku
Y29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1
dGhvcml0eSAtIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv3Fi
CPH6WTT3G8kYo/eASVjpIoMTpsUgQwE7hPHmhUmfJ+r2hBtOoLTbcJjHMgGxBT4H
Tu70+k8vWTAi56sZVmvigAf88xZ1gDlRe+X5NbZ0TqmNghPktj+pA4P6or6KFWp/
3gvDthkUBcrqw6gElDtGfDIN8wBmIsiNaW02jBEYt9OyHGC0OPoCjM7T3UYH3go+
6118yHz7sCtTpJJiaVElBWEaRIGMLKlDliPfrDqBmg4pxRyp6V0etp6eMAo5zvGI
gPtLXcwy7IViQyU0AlYnAZG0O3AqP26x6JyIAX2f1PnbU21gnb8s51iruF9G/M7E
GwM8CetJMVxpRrPgRwIDAQABo4IBFzCCARMwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9BUFuIMGU2g/eMB8GA1Ud
IwQYMBaAFNLEsNKR1EwRcbNhyz2h/t2oatTjMDQGCCsGAQUFBwEBBCgwJjAkBggr
BgEFBQcwAYYYaHR0cDovL29jc3AuZ29kYWRkeS5jb20vMDIGA1UdHwQrMCkwJ6Al
oCOGIWh0dHA6Ly9jcmwuZ29kYWRkeS5jb20vZ2Ryb290LmNybDBGBgNVHSAEPzA9
MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cHM6Ly9jZXJ0cy5nb2RhZGR5LmNv
bS9yZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEAWQtTvZKGEacke+1bMc8d
H2xwxbhuvk679r6XUOEwf7ooXGKUwuN+M/f7QnaF25UcjCJYdQkMiGVnOQoWCcWg
OJekxSOTP7QYpgEGRJHjp2kntFolfzq3Ms3dhP8qOCkzpN1nsoX+oYggHFCJyNwq
9kIDN0zmiN/VryTyscPfzLXs4Jlet0lUIDyUGAzHHFIYSaRt4bNYC8nY7NmuHDKO
KHAN4v6mF56ED71XcLNa6R+ghlO773z/aQvgSMO3kwvIClTErF0UZzdsyqUvMQg3
qm5vjLyb4lddJIGvl5echK1srDdMZvNhkREg5L4wn3qkKQmw4TRfZHcYQFHfjDCm
rw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
ReYNnyicsbkqWletNw+vHX/bvZ8=
-----END CERTIFICATE-----

View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC4EN34fKbxwJ+z
QpGcSatVcoDPA1ke6gmUueWzKmqnHhXa5cvmwfvNFin3XV53A9aVCkO+0jbBGcgt
Q0/hIpjq6PBiE1Zf4rmXOkLQzP2Xl5yg0q78Ri+4+RLzlGGABtVhL2S8zabSJlha
AGRRe4ffh5smRlohLAmg67pxjQiacLW6KzJB/KJurrGt0jWgHTPXilc61+shHPgD
dxXKGPx0Mc/a1e29xOMY1aAJCUcrs4oW9CE8mGmxWLiyOruFCJThIX9Egq+1uCgi
nqbsEi4NjM1UYoriEYGVKiMyPDoubWudZg2KGj8Qs9Wx4jQir16inQDI+hHjxbRJ
GIMNpOZTAgMBAAECggEBAJtIl4r/1nOTdudrXJ6GRAYlQGfkwjXjacvP/Onm+e0c
44E1Zoy50G1XqnXmjkBHu6sm6ro8bDcCQi91Xxlm760WcV28RJ1GEB5151Jx7esK
2/eNZlSr/azGbGeUIaE5oqCHtCvYL0mRUe4z8G4RkjJRG+Hxbi4YEdNxq2wKeFyZ
EqZXBPfw259tY5lIZn3lE+3IuDJw9LDOVT/xq/ZFHgULbPYEBOj8tp/BbF6JOrjl
CPOkjdRIM8ompztlxBce3biVXVFP22dH9D5221Cj3sYc79LkONOjaKWklsGCjbNO
UCcZJZ70hZpdJCUBN2CMJcolBH+xT5B+kPnyj2pRQlECgYEA9UlbXTmGAyEacJVp
FfwVEIVjIJOxm5XZ7uI0/06MURviMDfVsOdXrswF6GcoJo1VT88Cmz1zn1/olPEW
Zardwch/8TXbA5+hUXEUN68h9mfZucliewZePX5uPN5+WiaClZ5WQjUTpjR1IFGk
Y3wn55B15ZKZyw7EPtulnpcvYokCgYEAwBr6espToQ57rU4Vh92T/pSuhumPZJIm
yVVhf+iEQT9Y9BSfM9reYxhwVZQVTdryQaFz0yQ1XIxG2tn6edfpnjUy+NAgsrdT
WAgzDKru0l7ht3/sr5By6yWRbyUYcPBV6FSAbiFKrV467YovVtcCfQdVNNUt8e7t
/ufQS8zqevsCgYEAkAnc2hjOhoXo9dX3WM6oPARoWpgAgyHzUWGKx6YDphmesLwJ
A5JGnkH28iupm0IBqBUjLbBfdmamuNf+VAOLp6Eq6KW8kBssaxvhSHXSltUTORN2
flIWAzx8Vcg+IIhexKevdb+fY0mIwkrPIxCkikn9wateHqz0Nwla749OZykCgYAc
O9rUcSgZY6eJsRA5B7fYksGT0n/gqBpLPOE3i1Tkwgqw1NcRJ/nHVrAr47e92ZAB
VVlQjuHI2FURlTfa8IDFX8w+BVjI62i0Z4AZPIYdJRTHg2Wl5/T72mmljC4rayc1
HjZB+WKgWFkQ0F5kxPT4qzs6qJo4FIWmESvr+BH+QQKBgGJ+ZT90jsERQfMzv6aL
OW8huYImT0NvRKqIG0K14amm1ku0G+rL8HMy0JIJUs0x5BqwacUEBHffQkAPQOIh
/6XBAsiZD10QlomuDMl1sOQSKacIOFlH8KFPM0RdgCRQk5oiYmdh2CeavkjkE9Cp
HpC22rgeJoxV9fq5Zd2diWJh
-----END PRIVATE KEY-----

Binary file not shown.

View File

@ -144,6 +144,7 @@ public class HttpClientUtilsTest {
}
}
@Test
@DisplayName("GET 成功")
public void get_Success() throws IOException {

View File

@ -48,6 +48,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
*/
@SpringBootTest
@DisplayName("ProtocolJsonUtils 测试类")
@SuppressWarnings("unchecked")
public class ProtocolJsonUtilsTest {
private ProtocolResp protocolResp;

View File

@ -1,122 +1,146 @@
package com.cmcc.magent.service.impl;
import com.cmcc.magent.config.PlatformServiceConfig;
import com.cmcc.magent.misc.HttpClientUtils;
import com.cmcc.magent.misc.JsonUtils;
import com.cmcc.hy.gzs.common.result.Result;
import com.cmcc.magent.pojo.po.RegisterAgent;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.AfterEach;
import com.cmcc.magent.service.PlatformApiFeignClientService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.test.context.SpringBootTest;
import org.slf4j.Logger;
import sun.misc.Unsafe;
import java.io.IOException;
import java.lang.reflect.Field;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mockStatic;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* 单元测试类 {@code PlatformApiServiceImplTest} 用于测试 {@link PlatformApiServiceImpl} 的功能
* PlatformApiServiceImplTest 用于测试 {@link PlatformApiServiceImpl} 的功能
* <p>
* 测试的主要目标是确保 {@link PlatformApiServiceImpl#registerAgent(RegisterAgent)} 方法能够正常工作
* 该测试类包含多个单元测试验证与 {@link PlatformApiFeignClientService} 相关的方法的正确性
* </p>
*
* <p>测试中使用了 {@code MockWebServer} 来模拟 HTTP 请求和响应避免依赖实际的外部服务</p>
*
* <p>主要验证内容包括</p>
* <ul>
* <li>是否正确构造了 HTTP 请求如方法和路径</li>
* <li>是否正确处理了 HTTP 响应并返回预期结果</li>
* </ul>
*
* <p>依赖注入说明</p>
* <ul>
* <li>通过 {@code @Resource} 注入被测试的 {@code PlatformApiServiceImpl}</li>
* <li>通过 {@code @Autowired} 注入 {@code WebClient.Builder}用于生成测试时专用的 {@code WebClient}</li>
* </ul>
*
* @author huangxin@cmhi.chinamobile.com
* @version 1.0.0
* @since 2025-01-14
* @since 2025-03-07
*/
@SpringBootTest
@DisplayName("平台服务接口")
@DisplayName("平台访问接口测试")
public class PlatformApiServiceImplTest {
/**
* 被测试的服务类 {@link PlatformApiServiceImpl}
*/
@Resource
@Mock
private PlatformApiFeignClientService platformApiServiceFeign;
@InjectMocks
private PlatformApiServiceImpl platformApiService;
@Resource
private PlatformServiceConfig platformServiceConfig;
private MockedStatic<HttpClientUtils> platformMock;
private MockedStatic<JsonUtils> jsonMock;
private Logger logger;
/**
* 在每个测试前进行设置
* 创建 HttpClient 和响应的 Mock 对象并初始化 Mockito
*
* 在每个测试之前初始化 Mockito 注解
*/
@BeforeEach
public void setUp() {
public void setUp() throws NoSuchFieldException, IllegalAccessException {
MockitoAnnotations.openMocks(this);
platformMock = mockStatic(HttpClientUtils.class, Mockito.CALLS_REAL_METHODS);
jsonMock = mockStatic(JsonUtils.class);
logger = mock(Logger.class);
// 获取 MyService Class 对象
Class<?> clazz = PlatformApiServiceImpl.class;
// 获取 log 字段
Field logField = clazz.getDeclaredField("log");
// 设置字段可访问
logField.setAccessible(true);
// 获取 Unsafe 实例
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
// 获取 log 字段的偏移量
long offset = unsafe.staticFieldOffset(logField);
// 获取 log 字段所属的类对象
Object base = unsafe.staticFieldBase(logField);
// 使用 Unsafe 修改 log 字段的值
unsafe.putObject(base, offset, logger);
}
/**
* 在每个测试后清理资源
*/
@AfterEach
public void tearDown() {
platformMock.close();
jsonMock.close();
}
/**
* 测试 {@link PlatformApiServiceImpl#registerAgent(RegisterAgent)} 方法
*
* <p>验证以下内容</p>
* <ul>
* <li>是否正确发送了 HTTP POST 请求到指定路径 {@code /register}</li>
* <li>是否正确处理了 HTTP 响应并返回预期的结果</li>
* </ul>
*
* <p>测试流程</p>
* <ol>
* <li>设置 MockWebServer 的响应内容为 {@code {"message": "Hello, World!"}}</li>
* <li>使用测试数据 {@link RegisterAgent} 对象调用 {@code registerAgent} 方法</li>
* <li>验证返回值是否等于设置的响应内容</li>
* <li>验证发送的请求是否符合预期如方法为 POST路径为 /register</li>
* </ol>
* 测试在成功执行情况下调用 responseDeploymentResult 方法返回结果
*
*/
@Test
@DisplayName("设备注册接口测试")
void testFetchData() throws IOException {
// 准备模拟的 HTTP 响应
String mockResponse = "Mocked Response";
@DisplayName("部署结果响应成功")
public void responseDeploymentResult_SuccessfulExecution_ReturnsResult() {
String deploymentId = "12345";
Integer status = 1;
Result<String> expectedResponse = Result.success("Deployment updated successfully");
final RegisterAgent agent = RegisterAgent.builder().deviceId("123542535").build();
when(platformApiServiceFeign.responseDeploymentResultFeign(deploymentId, status)).thenReturn(expectedResponse);
jsonMock.when(() -> JsonUtils.getJson(any(Object.class))).thenReturn(mockResponse);
Result<String> actualResponse = platformApiService.responseDeploymentResult(deploymentId, status);
platformMock.when(() -> HttpClientUtils.postJson(platformServiceConfig + "/register", null, mockResponse, null)).thenReturn(
"Mocked Response");
assertNotNull(actualResponse);
assertEquals(expectedResponse, actualResponse);
}
// 调用被测试方法
final String result = platformApiService.registerAgent(agent);
/**
* 测试在调用 responseDeploymentResult 方法时抛出异常返回 null
*
* @throws RuntimeException 可能抛出的异常
*/
@Test
@DisplayName("部署结果响应异常")
public void responseDeploymentResult_ExceptionThrown_ReturnsNull() {
String deploymentId = "12345";
Integer status = 1;
Exception e = new RuntimeException("Service exception");
// 验证结果
assertThat(result).isEqualTo(mockResponse);
when(platformApiServiceFeign.responseDeploymentResultFeign(deploymentId, status)).thenThrow(e);
Result<String> ret = platformApiService.responseDeploymentResult(deploymentId, status);
assertNull(ret);
verify(logger).error(eq("Response deployment {} result exception: {}"), eq("12345"), eq(e.getMessage()));
}
/**
* 测试在成功注册情况下调用 registerAgent 方法返回成功结果
*
*/
@Test
@DisplayName("注册代理成功")
public void registerAgent_SuccessfulRegistration_ReturnsSuccessResult() {
RegisterAgent agent = new RegisterAgent("1234567890");
Result<String> expected = Result.success("Registration successful");
when(platformApiServiceFeign.registerAgentFeign(agent)).thenReturn(expected);
Result<String> actual = platformApiService.registerAgent(agent);
assertEquals(expected, actual);
}
/**
* 测试在调用 registerAgent 方法时抛出异常返回 null
*
* @throws RuntimeException 可能抛出的异常
*/
@Test
@DisplayName("注册代理异常")
public void registerAgent_ExceptionThrown_ReturnsNull() {
RegisterAgent agent = new RegisterAgent("1234567890");
Exception e = new RuntimeException("Registration failedxxxx");
when(platformApiServiceFeign.registerAgentFeign(agent)).thenThrow(e);
Result<String> ret = platformApiService.registerAgent(agent);
assertNull(ret);
verify(logger).error(eq("Register agent client {} exception: {}"), eq("1234567890"), eq(e.getMessage()));
}
}

View File

@ -82,6 +82,7 @@ public class ResourceUsageServiceImplTest {
resourceUsageService.performTask();
@SuppressWarnings("unchecked")
CircularQueue<ResourceUsage> resourceUsageQueue = (CircularQueue<ResourceUsage>) ReflectionTestUtils.getField(resourceUsageService,
"resourceUsageQueue");
assertNotNull(resourceUsageQueue, "Resource usage queue should not be null");
@ -109,6 +110,7 @@ public class ResourceUsageServiceImplTest {
resourceUsageService.performTask();
@SuppressWarnings("unchecked")
CircularQueue<ResourceUsage> resourceUsageQueue = (CircularQueue<ResourceUsage>) ReflectionTestUtils.getField(resourceUsageService,
"resourceUsageQueue");
@ -137,6 +139,7 @@ public class ResourceUsageServiceImplTest {
resourceUsageService.performTask();
@SuppressWarnings("unchecked")
CircularQueue<ResourceUsage> resourceUsageQueue = (CircularQueue<ResourceUsage>) ReflectionTestUtils.getField(resourceUsageService,
"resourceUsageQueue");
assertNotNull(resourceUsageQueue, "Resource usage queue should not be null");

View File

@ -59,7 +59,7 @@ protocol.crypto-type=0
# Platform Service
# Manager Platform URL
service.platform-url=http://xajhuang.com:1300
service.platform-url=http://xajhuang.com:3006/post
# APPID
service.platform-appid=appid
# cluster name
@ -73,3 +73,5 @@ thread.max-pool-size=10
thread.queue-capacity=25
thread.name-prefix=Async-
gzs.sign.client-details-enabled=true
gzs.sign.client-details.'mw-open-82hsbmz8'=98rnk8pz6j08fp6q