diff --git a/pom.xml b/pom.xml index f35f0cf..59dee0a 100644 --- a/pom.xml +++ b/pom.xml @@ -67,6 +67,12 @@ spring-security-test test + + org.junit.platform + junit-platform-suite-engine + 1.10.2 + test + org.springframework.boot spring-boot-starter-undertow diff --git a/src/main/java/com/cmhi/cf/controller/CommonFrameworkApi.java b/src/main/java/com/cmhi/cf/controller/CommonFrameworkApi.java index 69fce74..e9f5ebf 100644 --- a/src/main/java/com/cmhi/cf/controller/CommonFrameworkApi.java +++ b/src/main/java/com/cmhi/cf/controller/CommonFrameworkApi.java @@ -5,6 +5,7 @@ import com.cmhi.cf.restapi.annotation.DecryptionProtocol; import com.cmhi.cf.restapi.annotation.EncryptionProtocol; import com.cmhi.cf.restapi.annotation.OperationLogAnnotation; import com.cmhi.cf.restapi.pojo.base.BaseRespStatus; +import com.cmhi.cf.restapi.pojo.po.VersionInfo; import com.cmhi.cf.restapi.pojo.vo.ProtocolResp; import com.cmhi.cf.restapi.pojo.vo.VersionResp; import io.swagger.v3.oas.annotations.tags.Tag; @@ -31,7 +32,14 @@ public class CommonFrameworkApi { @OperationLogAnnotation(OperationModule = "通用模块", OperationType = "读取", OperationDesc = "获取当前系统版本信息") public ProtocolResp getVersion() { return ProtocolResp.result(VersionResp.builder() - .version(prgVer) + .version(VersionInfo.builder() + .commitId(prgVer.getCommitId()) + .commitDescribe(prgVer.getCommitDescribe()) + .commitTime(prgVer.getCommitTime()) + .tagName(prgVer.getTagName()) + .buildTime(prgVer.getBuildTime()) + .gitBranch(prgVer.getGitBranch()) + .build()) .build()); } @@ -41,7 +49,14 @@ public class CommonFrameworkApi { @OperationLogAnnotation(OperationModule = "通用模块", OperationType = "读取", OperationDesc = "获取当前系统版本信息") public ProtocolResp getVersionV2() { return ProtocolResp.result(VersionResp.builder() - .version(prgVer) + .version(VersionInfo.builder() + .commitId(prgVer.getCommitId()) + .commitDescribe(prgVer.getCommitDescribe()) + .commitTime(prgVer.getCommitTime()) + .tagName(prgVer.getTagName()) + .buildTime(prgVer.getBuildTime()) + .gitBranch(prgVer.getGitBranch()) + .build()) .build()); } } diff --git a/src/main/java/com/cmhi/cf/misc/HelperUtils.java b/src/main/java/com/cmhi/cf/misc/HelperUtils.java index a8ae1ce..f9418ef 100644 --- a/src/main/java/com/cmhi/cf/misc/HelperUtils.java +++ b/src/main/java/com/cmhi/cf/misc/HelperUtils.java @@ -28,11 +28,13 @@ import java.sql.Timestamp; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; +import java.util.Arrays; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.Stack; public class HelperUtils { public static final String UN_EXPECT_REGEX_CHARS = "^((?!(--|\\s|\\*|%|\\+|'|;])).)*$"; @@ -41,7 +43,7 @@ public class HelperUtils { DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); public static String truncateString(String orgString, int maxLength) { - if(!stringNotEmptyOrNull(orgString) || orgString.length() <= maxLength) { + if (!stringNotEmptyOrNull(orgString) || orgString.length() <= maxLength) { return orgString; } else { return orgString.substring(0, maxLength - 4) + "..."; @@ -114,6 +116,9 @@ public class HelperUtils { return OBJ_MAPPER.readValue(inputStream2String(is), valueTypeRef); } + public static T jsonGetObject(String json, TypeReference valueTypeRef) throws IOException { + return OBJ_MAPPER.readValue(json, valueTypeRef); + } private static Type createRespType(Class c) { return new ParameterizedType() { @@ -137,9 +142,50 @@ public class HelperUtils { }; } - public static ProtocolResp jsonGetProtocolResp(String reqJson, + public static ProtocolResp jsonGetProtocolResp(String jsonString, Class subClass) throws JsonProcessingException { - return OBJ_MAPPER.readValue(reqJson, new TypeReference<>() { + return OBJ_MAPPER.readValue(jsonString, new TypeReference<>() { + @Override + public Type getType() { + return createRespType(subClass); + } + }); + } + + private static Type createRespType(Class[] c) { + if (c.length == 1) { + return JsonParameterizedType.make(ProtocolResp.class, + new Type[] {c[0]}, + ProtocolResp.class.getDeclaringClass()); + } + + Stack> st = new Stack<>(); + + Arrays.stream(c).forEach(st::push); + + Class fc = st.pop(); + Class sc = st.pop(); + JsonParameterizedType type = JsonParameterizedType.make(sc, + new Type[] {fc}, + sc.getDeclaringClass()); + + while (!st.isEmpty()) { + Class mc = st.pop(); + type = JsonParameterizedType.make(mc, + new Type[] {type}, + mc.getDeclaringClass()); + } + + type = JsonParameterizedType.make(ProtocolResp.class, + new Type[] {type}, + ProtocolResp.class.getDeclaringClass()); + + return type; + } + + public static ProtocolResp jsonGetProtocolResp(String jsonString, + Class[] subClass) throws JsonProcessingException { + return OBJ_MAPPER.readValue(jsonString, new TypeReference<>() { @Override public Type getType() { return createRespType(subClass); @@ -193,7 +239,7 @@ public class HelperUtils { String localhostIp = "127.0.0.1"; // 客户端与服务器同为一台机器,获取的 ip 有时候是 ipv6 格式 String localhostIpv6 = "0:0:0:0:0:0:0:1"; - String separator = ","; + String separator = ","; if (request == null) { return "unknown"; diff --git a/src/main/java/com/cmhi/cf/misc/JsonParameterizedType.java b/src/main/java/com/cmhi/cf/misc/JsonParameterizedType.java new file mode 100644 index 0000000..46cc931 --- /dev/null +++ b/src/main/java/com/cmhi/cf/misc/JsonParameterizedType.java @@ -0,0 +1,112 @@ +package com.cmhi.cf.misc; + +import java.lang.reflect.MalformedParameterizedTypeException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.Arrays; +import java.util.Objects; + +public class JsonParameterizedType implements ParameterizedType { + private final Type[] actualTypeArguments; + private final Class rawType; + private final Type ownerType; + + private JsonParameterizedType(Class var1, Type[] var2, Type var3) { + this.actualTypeArguments = var2; + this.rawType = var1; + this.ownerType = (Type)(var3 != null ? var3 : var1.getDeclaringClass()); + this.validateConstructorArguments(); + } + + private void validateConstructorArguments() { + TypeVariable[] var1 = this.rawType.getTypeParameters(); + if (var1.length != this.actualTypeArguments.length) { + throw new MalformedParameterizedTypeException(); + } else { + for(int var2 = 0; var2 < this.actualTypeArguments.length; ++var2) { + } + } + } + + @Override + public Type[] getActualTypeArguments() { + return this.actualTypeArguments.clone(); + } + + @Override + public Type getRawType() { + return this.rawType; + } + + @Override + public Type getOwnerType() { + return this.ownerType; + } + + @Override + public boolean equals(Object var1) { + if (var1 instanceof ParameterizedType var2) { + if (this == var2) { + return true; + } else { + Type var3 = var2.getOwnerType(); + Type var4 = var2.getRawType(); + return Objects.equals(this.ownerType, var3) && Objects.equals(this.rawType, var4) && Arrays.equals(this.actualTypeArguments, var2.getActualTypeArguments()); + } + } else { + return false; + } + } + + @Override + public int hashCode() { + return Arrays.hashCode(this.actualTypeArguments) ^ Objects.hashCode(this.ownerType) ^ Objects.hashCode(this.rawType); + } + + @Override + public String toString() { + StringBuilder var1 = new StringBuilder(); + if (this.ownerType != null) { + if (this.ownerType instanceof Class) { + var1.append(((Class)this.ownerType).getName()); + } else { + var1.append(this.ownerType.toString()); + } + + var1.append("$"); + if (this.ownerType instanceof JsonParameterizedType) { + var1.append(this.rawType.getName().replace(((JsonParameterizedType)this.ownerType).rawType.getName() + "$", "")); + } else { + var1.append(this.rawType.getSimpleName()); + } + } else { + var1.append(this.rawType.getName()); + } + + if (this.actualTypeArguments != null && this.actualTypeArguments.length > 0) { + var1.append("<"); + boolean var2 = true; + Type[] var3 = this.actualTypeArguments; + int var4 = var3.length; + + for(int var5 = 0; var5 < var4; ++var5) { + Type var6 = var3[var5]; + if (!var2) { + var1.append(", "); + } + + var1.append(var6.getTypeName()); + var2 = false; + } + + var1.append(">"); + } + + return var1.toString(); + } + + public static JsonParameterizedType make(Class var0, Type[] var1, Type var2) { + return new JsonParameterizedType(var0, var1, var2); + } +} diff --git a/src/main/java/com/cmhi/cf/restapi/pojo/base/BasePageResultResp.java b/src/main/java/com/cmhi/cf/restapi/pojo/base/BasePageResultResp.java index 2abd25e..84315b3 100644 --- a/src/main/java/com/cmhi/cf/restapi/pojo/base/BasePageResultResp.java +++ b/src/main/java/com/cmhi/cf/restapi/pojo/base/BasePageResultResp.java @@ -3,15 +3,19 @@ package com.cmhi.cf.restapi.pojo.base; import com.cmhi.cf.restapi.pojo.po.PageResults; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; @EqualsAndHashCode(callSuper = true) @Data @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({"items", "status", "message"}) @Builder +@NoArgsConstructor +@AllArgsConstructor public class BasePageResultResp extends BaseRespStatus { private PageResults items; } diff --git a/src/main/java/com/cmhi/cf/restapi/pojo/po/VersionInfo.java b/src/main/java/com/cmhi/cf/restapi/pojo/po/VersionInfo.java new file mode 100644 index 0000000..68aff5a --- /dev/null +++ b/src/main/java/com/cmhi/cf/restapi/pojo/po/VersionInfo.java @@ -0,0 +1,19 @@ +package com.cmhi.cf.restapi.pojo.po; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class VersionInfo { + private String commitId; + private String commitDescribe; + private String commitTime; + private String tagName; + private String buildTime; + private String gitBranch; +} diff --git a/src/main/java/com/cmhi/cf/restapi/pojo/vo/VersionResp.java b/src/main/java/com/cmhi/cf/restapi/pojo/vo/VersionResp.java index ec85d66..6e5616b 100644 --- a/src/main/java/com/cmhi/cf/restapi/pojo/vo/VersionResp.java +++ b/src/main/java/com/cmhi/cf/restapi/pojo/vo/VersionResp.java @@ -1,16 +1,20 @@ package com.cmhi.cf.restapi.pojo.vo; -import com.cmhi.cf.configure.ProjectGitVersionInfo; import com.cmhi.cf.restapi.pojo.base.BaseRespStatus; +import com.cmhi.cf.restapi.pojo.po.VersionInfo; import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; @EqualsAndHashCode(callSuper = true) @Data @JsonPropertyOrder({"version", "status", "message"}) @Builder +@NoArgsConstructor +@AllArgsConstructor public class VersionResp extends BaseRespStatus { - private ProjectGitVersionInfo version; + private VersionInfo version; } diff --git a/src/test/java/com/cmhi/cf/tools/ToolsTest.java b/src/test/java/com/cmhi/cf/tools/ToolsTest.java index 4e4af0c..c0760b3 100644 --- a/src/test/java/com/cmhi/cf/tools/ToolsTest.java +++ b/src/test/java/com/cmhi/cf/tools/ToolsTest.java @@ -1,9 +1,16 @@ package com.cmhi.cf.tools; +import com.cmhi.cf.misc.JsonParameterizedType; +import com.cmhi.cf.restapi.pojo.base.BasePageResultResp; +import com.cmhi.cf.restapi.pojo.po.OperationLogSummary; +import com.cmhi.cf.restapi.pojo.vo.ProtocolResp; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import com.jayway.jsonpath.JsonPath; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; +import java.lang.reflect.Type; import java.util.UUID; @Slf4j @@ -27,8 +34,164 @@ public class ToolsTest { @Test public void testGenUuid() { - for(int i = 10; i < 100; i++) { + for (int i = 10; i < 100; i++) { log.info("{}: {}", i, UUID.randomUUID()); } } + + @Test + public void jsonToObject() throws Exception { + final String json = """ + { + "ver": 1, + "cryptoType": 0, + "timeStamp": 1707101107092, + "code": 200, + "msgContent": { + "items": { + "pageNumber": 1, + "pageSize": 10, + "totalPage": 1, + "totalRow": 7, + "items": [ + { + "id": 1, + "module": "系统安全模块", + "operationType": "认证/鉴权", + "operationStatus": "成功", + "description": "[admin] login", + "requestIp": "172.21.96.1", + "callFunction": "login", + "httpMethod": "POST", + "httpPath": "/api/login", + "userId": 1, + "expendTime": 453, + "transmitDelay": 139, + "operationTime": "2024-02-05T02:23:57.589+00:00" + }, + { + "id": 3, + "module": "系统安全模块", + "operationType": "认证/鉴权", + "operationStatus": "成功", + "description": "[admin] login", + "requestIp": "172.21.96.1", + "callFunction": "login", + "httpMethod": "POST", + "httpPath": "/api/login", + "userId": 1, + "expendTime": 464, + "transmitDelay": 128, + "operationTime": "2024-02-05T02:24:32.212+00:00" + }, + { + "id": 5, + "module": "系统安全模块", + "operationType": "认证/鉴权", + "operationStatus": "成功", + "description": "[admin] login", + "requestIp": "172.21.96.1", + "callFunction": "login", + "httpMethod": "POST", + "httpPath": "/api/login", + "userId": 1, + "expendTime": 435, + "transmitDelay": 137, + "operationTime": "2024-02-05T02:25:39.344+00:00" + }, + { + "id": 7, + "module": "系统安全模块", + "operationType": "认证/鉴权", + "operationStatus": "成功", + "description": "[admin] login", + "requestIp": "172.21.96.1", + "callFunction": "login", + "httpMethod": "POST", + "httpPath": "/api/login", + "userId": 1, + "expendTime": 470, + "transmitDelay": 129, + "operationTime": "2024-02-05T02:26:37.216+00:00" + }, + { + "id": 9, + "module": "系统安全模块", + "operationType": "认证/鉴权", + "operationStatus": "成功", + "description": "[admin] login", + "requestIp": "172.21.96.1", + "callFunction": "login", + "httpMethod": "POST", + "httpPath": "/api/login", + "userId": 1, + "expendTime": 411, + "transmitDelay": 124, + "operationTime": "2024-02-05T02:39:48.214+00:00" + }, + { + "id": 11, + "module": "系统安全模块", + "operationType": "认证/鉴权", + "operationStatus": "成功", + "description": "[admin] login", + "requestIp": "172.21.96.1", + "callFunction": "login", + "httpMethod": "POST", + "httpPath": "/api/login", + "userId": 1, + "expendTime": 468, + "transmitDelay": 124, + "operationTime": "2024-02-05T02:40:16.012+00:00" + }, + { + "id": 13, + "module": "系统安全模块", + "operationType": "认证/鉴权", + "operationStatus": "成功", + "description": "[admin] login", + "requestIp": "172.21.96.1", + "callFunction": "login", + "httpMethod": "POST", + "httpPath": "/api/login", + "userId": 1, + "expendTime": 473, + "transmitDelay": 121, + "operationTime": "2024-02-05T02:45:05.815+00:00" + } + ] + }, + "status": 0, + "message": [ + "成功" + ] + } + } + """; + + ProtocolResp> ret = null; + + JsonParameterizedType type = JsonParameterizedType.make(BasePageResultResp.class, + new java.lang.Class[] {OperationLogSummary.class}, + BasePageResultResp.class.getDeclaringClass()); + + ret = new ObjectMapper().readValue(json, new TypeReference<>() { + @Override + public Type getType() { + return JsonParameterizedType.make(ProtocolResp.class, + new java.lang.Class[] {(Class) type.getRawType()}, + ProtocolResp.class.getDeclaringClass()); + } + }); + + log.info("{}", ret); + + ret = new ObjectMapper().readValue(json, new TypeReference<>() { + }); + + log.info("{}", ret); + + Class[] classes = { String.class, Integer.class, Double.class }; + } + } diff --git a/src/test/utest/IntegrationTestSuite.java b/src/test/utest/IntegrationTestSuite.java new file mode 100644 index 0000000..ac1f3c3 --- /dev/null +++ b/src/test/utest/IntegrationTestSuite.java @@ -0,0 +1,11 @@ +import com.cmhi.cf.controller.CommonFrameworkApiTest; +import com.cmhi.cf.controller.OperationLogApiTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.platform.suite.api.SelectClasses; +import org.junit.platform.suite.api.Suite; + +@SelectClasses({CommonFrameworkApiTest.class, OperationLogApiTest.class}) +@DisplayName("接口集成测试") +@Suite +public class IntegrationTestSuite { +} diff --git a/src/test/utest/com/cmhi/cf/common/TestBaseAuthentication.java b/src/test/utest/com/cmhi/cf/common/TestBaseAuthentication.java new file mode 100644 index 0000000..92ed459 --- /dev/null +++ b/src/test/utest/com/cmhi/cf/common/TestBaseAuthentication.java @@ -0,0 +1,158 @@ +package com.cmhi.cf.common; + +import com.cmhi.cf.authentication.pojo.dto.LoginReq; +import com.cmhi.cf.authentication.pojo.vo.LoginResp; +import com.cmhi.cf.misc.HelperUtils; +import com.cmhi.cf.restapi.config.ProtoCryptoType; +import com.cmhi.cf.restapi.config.ProtocolConfigure; +import com.cmhi.cf.restapi.pojo.dto.ProtocolReq; +import com.cmhi.cf.restapi.pojo.vo.ProtocolResp; +import com.cmhi.cf.restapi.service.ProtocolSecurityService; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.util.Objects; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@AutoConfigureMockMvc +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public abstract class TestBaseAuthentication { + protected static final ThreadLocal headersThreadLocal = new ThreadLocal<>(); + + @Autowired + protected MockMvc mockMvc; + + @Autowired + private ProtocolSecurityService securityService; + + public HttpHeaders getHeaders() { + return headersThreadLocal.get(); + } + + @BeforeAll + public void setUpClass() throws Exception { + LoginReq logReq = LoginReq.builder() + .username("admin") + .password("8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918") + .build(); + + ProtocolReq loginPro = new ProtocolReq<>(); + loginPro.setMsgContent(logReq); + loginPro.setVer(1); + loginPro.setTimeStamp(System.currentTimeMillis()); + loginPro.setCryptoType(ProtocolConfigure.SECURITY_PROTOCOL_TYPE); + + MvcResult mvcResult = mockMvc.perform(post("/api/login") + .contentType(MediaType.APPLICATION_JSON) // Set the content type to JSON + .content(HelperUtils.getJson(loginPro))) // Pass the JSON request body + .andExpect(status().isOk()) // Expect that the status is 200 OK + .andReturn(); + + // 假设JWT在响应体中返回。您需要根据实际情况调整此行代码。 + String respJson = mvcResult.getResponse().getContentAsString(); + Assertions.assertNotNull(respJson); + Assertions.assertNotEquals(respJson.length(), 0); + ProtocolResp resp = HelperUtils.jsonGetProtocolResp(respJson, LoginResp.class); + + Assertions.assertNotNull(resp); + Assertions.assertNotNull(resp.getMsgContent()); + Assertions.assertEquals(resp.getCode(), HttpStatus.OK.value()); + + LoginResp loginResp = (LoginResp) resp.getMsgContent(); + + Assertions.assertEquals(loginResp.getStatus(), ErrorCode.ERR_OK.getCode()); + Assertions.assertNotNull(loginResp.getToken()); + Assertions.assertNotEquals(loginResp.getToken().length(), 0); + + HttpHeaders headers = new HttpHeaders(); + MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8"); + headers.setContentType(type); + headers.add("Accept", MediaType.APPLICATION_JSON.toString()); + headers.add(HttpHeaders.ACCEPT_ENCODING, "gzip, deflate, br"); + headers.setBearerAuth(loginResp.getToken()); + headersThreadLocal.set(headers); + } + + public Object performanceRestful(RequestMethod reqType, T reqObject, String urlPath, Class[] subRespClass) throws Exception { + MockHttpServletRequestBuilder build = createMockMvcBuilder(urlPath, reqType); + + if (Objects.nonNull(reqObject)) { + String sendMsgContent; + ProtocolReq reqInfo = new ProtocolReq<>(); + reqInfo.setVer(ConstValue.Protocol.VERSION); + reqInfo.setCryptoType(ProtocolConfigure.SECURITY_PROTOCOL_TYPE); + reqInfo.setTimeStamp(System.currentTimeMillis()); + reqInfo.setMsgContent(reqObject); + + if (ProtocolConfigure.SECURITY_PROTOCOL_TYPE != ProtoCryptoType.CRYPTO_NONE.getValue()) { + String cipherText = securityService.encryptProtocolString(HelperUtils.getJson(reqObject), + ProtocolConfigure.SECURITY_PROTOCOL_TYPE); + + ProtocolReq cipherInfo = new ProtocolReq<>(); + cipherInfo.setVer(reqInfo.getVer()); + cipherInfo.setCryptoType(reqInfo.getCryptoType()); + cipherInfo.setTimeStamp(System.currentTimeMillis()); + cipherInfo.setMsgContent(cipherText); + sendMsgContent = HelperUtils.getJson(cipherInfo); + } else { + sendMsgContent = HelperUtils.getJson(reqInfo); + } + + build.content(sendMsgContent); + } + + + String rspValue = mockMvc.perform(build) + .andDo(print()) + .andReturn() + .getResponse() + .getContentAsString(); + + AssertValidString(rspValue); + + rspValue = securityService.decryptProtocol(rspValue); + AssertValidString(rspValue); + + ProtocolResp resp = HelperUtils.jsonGetProtocolResp(rspValue, subRespClass); + + Assertions.assertNotNull(resp); + Assertions.assertNotNull(resp.getMsgContent()); + Assertions.assertEquals(resp.getCode(), HttpStatus.OK.value()); + + return resp.getMsgContent(); + } + + private MockHttpServletRequestBuilder createMockMvcBuilder(String uri, RequestMethod reqType) { + MockHttpServletRequestBuilder build = switch (reqType) { + case PUT -> MockMvcRequestBuilders.put(uri); + case GET -> MockMvcRequestBuilders.get(uri); + case DELETE -> MockMvcRequestBuilders.delete(uri); + default -> MockMvcRequestBuilders.post(uri); + }; + + build.accept(MediaType.APPLICATION_JSON); + build.headers(getHeaders()); + return build; + } + + public void AssertValidString(String str) { + Assertions.assertNotNull(str); + Assertions.assertFalse(str.isEmpty()); + } +} diff --git a/src/test/utest/com/cmhi/cf/common/authentication/TestCommonExtension.java b/src/test/utest/com/cmhi/cf/common/authentication/TestCommonExtension.java new file mode 100644 index 0000000..5454d41 --- /dev/null +++ b/src/test/utest/com/cmhi/cf/common/authentication/TestCommonExtension.java @@ -0,0 +1,89 @@ +package com.cmhi.cf.common.authentication; + +import com.cmhi.cf.authentication.pojo.dto.LoginReq; +import com.cmhi.cf.misc.HelperUtils; +import com.cmhi.cf.restapi.config.ProtocolConfigure; +import com.cmhi.cf.restapi.pojo.dto.ProtocolReq; +import jakarta.annotation.Resource; +import lombok.Getter; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.ResultMatcher; + +import static org.springframework.test.web.client.match.MockRestRequestMatchers.content; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@ExtendWith({SpringExtension.class}) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@AutoConfigureMockMvc +public class TestCommonExtension implements BeforeEachCallback { + @Getter + private static final TestRestTemplate restTemplate = new TestRestTemplate(); + private static final ThreadLocal headersThreadLocal = new ThreadLocal<>(); + + @Resource + private MockMvc mockMvc; + + public static HttpHeaders getHeaders() { + return headersThreadLocal.get(); + } + + + @Override + public void beforeEach(ExtensionContext extensionContext) throws Exception { + HttpHeaders headers = new HttpHeaders(); + MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8"); + headers.setContentType(type); + headers.add("Accept", MediaType.APPLICATION_JSON.toString()); + //headers.add(HttpHeaders.ACCEPT_ENCODING, "gzip, deflate, br"); + + LoginReq logReq = LoginReq.builder() + .username("admin") + .password("8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918") + .build(); + + ProtocolReq loginPro = new ProtocolReq<>(); + loginPro.setMsgContent(logReq); + loginPro.setVer(1); + loginPro.setTimeStamp(System.currentTimeMillis()); + loginPro.setCryptoType(ProtocolConfigure.SECURITY_PROTOCOL_TYPE); + + MvcResult mvcResult = mockMvc.perform(post("/api/login") + .contentType(MediaType.APPLICATION_JSON) // Set the content type to JSON + .content(HelperUtils.getJson(loginPro))) // Pass the JSON request body + .andExpect(status().isOk()) // Expect that the status is 200 OK + .andExpect((ResultMatcher) content().contentType( + MediaType.APPLICATION_JSON)) // Optional: Expect JSON response + .andReturn(); + +// HttpEntity formEntity = new HttpEntity<>(HelperUtils.getJson(loginPro), headers); +// +// ResponseEntity response = restTemplate.postForEntity(CommonConfigure.BASEURL + "/api/login", formEntity, String.class); +// Assertions.assertNotNull(response); +// +// ProtocolResp resp = HelperUtils.jsonGetProtocolResp(response.getBody(), LoginResp.class); +// Assertions.assertNotNull(resp); +// Assertions.assertNotNull(resp.getMsgContent()); +// Assertions.assertEquals(resp.getCode(), HttpStatus.OK.value()); +// +// LoginResp loginResp = (LoginResp) resp.getMsgContent(); +// +// Assertions.assertEquals(loginResp.getStatus(), ErrorCode.ERR_OK.getCode()); +// Assertions.assertNotNull(loginResp.getToken()); +// Assertions.assertNotEquals(loginResp.getToken().length(), 0); +// +// headers.setBearerAuth(loginResp.getToken()); +// + headersThreadLocal.set(headers); + } +} diff --git a/src/test/utest/com/cmhi/cf/controller/CommonFrameworkApiTest.java b/src/test/utest/com/cmhi/cf/controller/CommonFrameworkApiTest.java new file mode 100644 index 0000000..83f7455 --- /dev/null +++ b/src/test/utest/com/cmhi/cf/controller/CommonFrameworkApiTest.java @@ -0,0 +1,53 @@ +package com.cmhi.cf.controller; + +import com.cmhi.cf.common.ErrorCode; +import com.cmhi.cf.common.TestBaseAuthentication; +import com.cmhi.cf.restapi.pojo.vo.VersionResp; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.RequestMethod; + +@ExtendWith({SpringExtension.class}) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@Transactional +public class CommonFrameworkApiTest extends TestBaseAuthentication { + @Test + void testGetVersion() throws Exception { + VersionResp resp = (VersionResp) performanceRestful(RequestMethod.GET, null, "/api/version", new Class[]{VersionResp.class}); + Assertions.assertNotNull(resp); + Assertions.assertNotNull(resp.getVersion()); + Assertions.assertNotNull(resp.getStatus()); + Assertions.assertNotNull(resp.getMessage()); + Assertions.assertNotEquals(resp.getMessage().length, 0); + Assertions.assertEquals(resp.getStatus(), ErrorCode.ERR_OK.getCode()); + + Assertions.assertNotNull(resp.getVersion().getTagName()); + AssertValidString(resp.getVersion().getCommitId()); + AssertValidString(resp.getVersion().getCommitDescribe()); + AssertValidString(resp.getVersion().getCommitTime()); + AssertValidString(resp.getVersion().getBuildTime()); + AssertValidString(resp.getVersion().getGitBranch()); + } + + @Test + void testGetVersionV2() throws Exception { + VersionResp resp = (VersionResp) performanceRestful(RequestMethod.POST, null, "/api/version", new Class[]{VersionResp.class}); + Assertions.assertNotNull(resp); + Assertions.assertNotNull(resp.getVersion()); + Assertions.assertNotNull(resp.getStatus()); + Assertions.assertNotNull(resp.getMessage()); + Assertions.assertNotEquals(resp.getMessage().length, 0); + Assertions.assertEquals(resp.getStatus(), ErrorCode.ERR_OK.getCode()); + + Assertions.assertNotNull(resp.getVersion().getTagName()); + AssertValidString(resp.getVersion().getCommitId()); + AssertValidString(resp.getVersion().getCommitDescribe()); + AssertValidString(resp.getVersion().getCommitTime()); + AssertValidString(resp.getVersion().getBuildTime()); + AssertValidString(resp.getVersion().getGitBranch()); + } +} diff --git a/src/test/utest/com/cmhi/cf/controller/OperationLogApiTest.java b/src/test/utest/com/cmhi/cf/controller/OperationLogApiTest.java new file mode 100644 index 0000000..c76bc18 --- /dev/null +++ b/src/test/utest/com/cmhi/cf/controller/OperationLogApiTest.java @@ -0,0 +1,80 @@ +package com.cmhi.cf.controller; + +import com.cmhi.cf.common.ErrorCode; +import com.cmhi.cf.common.TestBaseAuthentication; +import com.cmhi.cf.restapi.pojo.base.BasePageResultResp; +import com.cmhi.cf.restapi.pojo.dto.OperationLogReq; +import com.cmhi.cf.restapi.pojo.po.OperationLogSummary; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.util.List; + +@ExtendWith({SpringExtension.class}) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@Transactional +public class OperationLogApiTest extends TestBaseAuthentication { + @Test + void testGetSummary() throws Exception { + final long pageSize = 10L; + final long pageNumber = 1L; + + OperationLogReq req = new OperationLogReq(); + req.setPageNumber(pageNumber); + req.setPageSize(pageSize); + req.setTotalSize(-1L); + + Object obj = performanceRestful(RequestMethod.POST, req, "/api/operation/summary", + new Class[] {BasePageResultResp.class, OperationLogSummary.class}); + Assertions.assertNotNull(obj); + BasePageResultResp resp = (BasePageResultResp) obj; + Assertions.assertNotNull(resp); + Assertions.assertNotNull(resp.getStatus()); + Assertions.assertNotNull(resp.getMessage()); + Assertions.assertNotEquals(resp.getMessage().length, 0); + Assertions.assertEquals(resp.getStatus(), ErrorCode.ERR_OK.getCode()); + + Assertions.assertNotNull(resp.getItems()); + Assertions.assertFalse(resp.getItems().getItems().isEmpty()); + Assertions.assertEquals(resp.getItems().getPageSize(), pageSize); + Assertions.assertEquals(resp.getItems().getPageNumber(), pageNumber); + Assertions.assertTrue(resp.getItems().getTotalPage() > 0); + Assertions.assertTrue(resp.getItems().getTotalRow() > 0); + + List items = resp.getItems().getItems(); + + for (Object o : items) { + Assertions.assertNotNull(o); + } + + resp.getItems().getItems().forEach(k -> { + Assertions.assertInstanceOf(OperationLogSummary.class, k); + OperationLogSummary o = (OperationLogSummary) k; + Assertions.assertNotNull(o); + Assertions.assertNotNull(o.getId()); + Assertions.assertNotNull(o.getOperationTime()); + AssertValidString(o.getModule()); + AssertValidString(o.getOperationType()); + AssertValidString(o.getOperationStatus()); + AssertValidString(o.getDescription()); + AssertValidString(o.getRequestIp()); + AssertValidString(o.getHttpMethod()); + AssertValidString(o.getHttpPath()); + }); + } + + @Test + void testGetDetails() throws Exception { + + } + + @Test + void testGetDetails_OperationLogServiceReturnsNoItems() throws Exception { + + } +}