No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sdk_token_test.go 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. package main
  2. import (
  3. "bytes"
  4. "context"
  5. "encoding/json"
  6. "fmt"
  7. "io"
  8. "net/http"
  9. "os/exec"
  10. "testing"
  11. "time"
  12. "git.x2erp.com/qdy/go-base/model/request/configreq"
  13. "git.x2erp.com/qdy/go-base/model/request/queryreq"
  14. "git.x2erp.com/qdy/go-base/sdk/configure"
  15. )
  16. // TestSDKTokenAuth 测试SDK使用Token认证进行数据库表字典操作
  17. func TestSDKTokenAuth(t *testing.T) {
  18. // 清除测试缓存
  19. cmd := exec.Command("go", "clean", "-testcache")
  20. if err := cmd.Run(); err != nil {
  21. t.Logf("清除测试缓存失败: %v", err)
  22. // 继续执行测试
  23. }
  24. // 1. 获取用户认证token
  25. authToken, err := getUserAuthToken(t)
  26. if err != nil {
  27. t.Fatalf("获取用户认证token失败: %v", err)
  28. }
  29. t.Logf("获取到用户认证token: %s...", authToken[:50])
  30. // 2. 使用认证token创建配置token
  31. configToken, err := createConfigToken(t, authToken)
  32. if err != nil {
  33. t.Fatalf("创建配置token失败: %v", err)
  34. }
  35. t.Logf("获取到配置token: %s...", configToken[:50])
  36. // 3. 使用配置token创建SDK客户端
  37. client, err := configure.NewTokenAuthClient("http://localhost:8080", configToken)
  38. if err != nil {
  39. t.Fatalf("创建SDK客户端失败: %v", err)
  40. }
  41. t.Log("SDK客户端创建成功")
  42. // 4. 测试SDK功能
  43. testTableID := fmt.Sprintf("test_sdk_table_%d", time.Now().Unix())
  44. ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  45. defer cancel()
  46. // 4.1 创建数据库表字典
  47. t.Run("CreateTableWithSDK", func(t *testing.T) {
  48. createTableWithSDK(t, ctx, client, testTableID)
  49. })
  50. // 4.2 查询数据库表字典详情
  51. t.Run("GetTableWithSDK", func(t *testing.T) {
  52. getTableWithSDK(t, ctx, client, testTableID)
  53. })
  54. // 4.3 查询数据库表字典列表
  55. t.Run("ListTablesWithSDK", func(t *testing.T) {
  56. listTablesWithSDK(t, ctx, client)
  57. })
  58. // 4.4 删除数据库表字典
  59. t.Run("DeleteTableWithSDK", func(t *testing.T) {
  60. deleteTableWithSDK(t, ctx, client, testTableID)
  61. })
  62. // 4.5 验证数据库表字典已删除
  63. t.Run("VerifyTableDeletedWithSDK", func(t *testing.T) {
  64. verifyTableDeletedWithSDK(t, ctx, client, testTableID)
  65. })
  66. t.Log("SDK Token认证测试全部通过")
  67. }
  68. // getUserAuthToken 获取用户认证token
  69. func getUserAuthToken(t *testing.T) (string, error) {
  70. httpClient := &http.Client{}
  71. // 用户登录
  72. loginURL := "http://localhost:8080/api/login/user"
  73. loginData := map[string]string{
  74. "user_id": "test-user-001",
  75. "password": "password123",
  76. }
  77. loginJSON, _ := json.Marshal(loginData)
  78. loginReq, err := http.NewRequest("POST", loginURL, bytes.NewReader(loginJSON))
  79. if err != nil {
  80. return "", fmt.Errorf("创建登录请求失败: %w", err)
  81. }
  82. loginReq.Header.Set("Content-Type", "application/json")
  83. loginResp, err := httpClient.Do(loginReq)
  84. if err != nil {
  85. return "", fmt.Errorf("发送登录请求失败: %w", err)
  86. }
  87. defer loginResp.Body.Close()
  88. loginBody, err := io.ReadAll(loginResp.Body)
  89. if err != nil {
  90. return "", fmt.Errorf("读取登录响应失败: %w", err)
  91. }
  92. var loginResult map[string]interface{}
  93. if err := json.Unmarshal(loginBody, &loginResult); err != nil {
  94. return "", fmt.Errorf("解析登录响应失败: %w", err)
  95. }
  96. if !loginResult["success"].(bool) {
  97. return "", fmt.Errorf("登录失败: %v", loginResult)
  98. }
  99. return loginResult["data"].(string), nil
  100. }
  101. // createConfigToken 创建配置token
  102. func createConfigToken(t *testing.T, authToken string) (string, error) {
  103. httpClient := &http.Client{}
  104. // 使用认证token创建配置token
  105. url := "http://localhost:8080/api/create/config/token"
  106. data := configreq.ConfigTokenRequest{
  107. ProjectID: "test-project",
  108. ServiceName: "test-service",
  109. ExpiresDays: 30,
  110. }
  111. jsonData, err := json.Marshal(data)
  112. if err != nil {
  113. return "", fmt.Errorf("JSON序列化失败: %w", err)
  114. }
  115. req, err := http.NewRequest("POST", url, bytes.NewReader(jsonData))
  116. if err != nil {
  117. return "", fmt.Errorf("创建请求失败: %w", err)
  118. }
  119. // Token Auth 认证
  120. req.Header.Set("Authorization", "Bearer "+authToken)
  121. req.Header.Set("Content-Type", "application/json")
  122. resp, err := httpClient.Do(req)
  123. if err != nil {
  124. return "", fmt.Errorf("发送请求失败: %w", err)
  125. }
  126. defer resp.Body.Close()
  127. body, err := io.ReadAll(resp.Body)
  128. if err != nil {
  129. return "", fmt.Errorf("读取响应失败: %w", err)
  130. }
  131. var result map[string]interface{}
  132. if err := json.Unmarshal(body, &result); err != nil {
  133. return "", fmt.Errorf("解析响应失败: %w", err)
  134. }
  135. if resp.StatusCode != 200 {
  136. return "", fmt.Errorf("期望状态码200,实际: %d", resp.StatusCode)
  137. }
  138. if !result["success"].(bool) {
  139. return "", fmt.Errorf("创建配置token失败: %v", result)
  140. }
  141. if data, ok := result["data"].(string); !ok || data == "" {
  142. return "", fmt.Errorf("未返回有效的配置token")
  143. } else {
  144. return data, nil
  145. }
  146. }
  147. // createTableWithSDK 使用SDK创建数据库表字典
  148. func createTableWithSDK(t *testing.T, ctx context.Context, client *configure.Client, tableID string) {
  149. req := &configure.DicTableRequest{
  150. TableID: tableID,
  151. TableType: "实体表",
  152. Name: "SDK测试表",
  153. Description: "使用SDK Token认证创建的测试表",
  154. Fields: []configure.DicTableFieldRequest{
  155. {
  156. FieldID: tableID + ".id",
  157. TableID: tableID,
  158. FiledType: "实际字段",
  159. DataType: "数值型",
  160. FieldName: "id",
  161. FieldNameCN: "主键ID",
  162. Description: "主键字段",
  163. },
  164. {
  165. FieldID: tableID + ".name",
  166. TableID: tableID,
  167. FiledType: "实际字段",
  168. DataType: "字符型",
  169. FieldName: "name",
  170. FieldNameCN: "名称",
  171. Description: "名称字段",
  172. },
  173. {
  174. FieldID: tableID + ".created_at",
  175. TableID: tableID,
  176. FiledType: "实际字段",
  177. DataType: "日期型",
  178. FieldName: "created_at",
  179. FieldNameCN: "创建时间",
  180. Description: "创建时间字段",
  181. },
  182. },
  183. }
  184. detail, err := client.SaveTable(ctx, req)
  185. if err != nil {
  186. t.Fatalf("使用SDK创建表失败: %v", err)
  187. }
  188. if detail.Table.TableID != tableID {
  189. t.Errorf("期望表ID: %s, 实际: %s", tableID, detail.Table.TableID)
  190. }
  191. if len(detail.Fields) != 3 {
  192. t.Errorf("期望字段数: 3, 实际: %d", len(detail.Fields))
  193. }
  194. t.Logf("使用SDK创建表成功: %s, 包含 %d 个字段", tableID, len(detail.Fields))
  195. }
  196. // getTableWithSDK 使用SDK查询数据库表字典详情
  197. func getTableWithSDK(t *testing.T, ctx context.Context, client *configure.Client, tableID string) {
  198. detail, err := client.GetTable(ctx, tableID)
  199. if err != nil {
  200. t.Fatalf("使用SDK查询表详情失败: %v", err)
  201. }
  202. if detail.Table.TableID != tableID {
  203. t.Errorf("期望表ID: %s, 实际: %s", tableID, detail.Table.TableID)
  204. }
  205. if detail.Table.Name != "SDK测试表" {
  206. t.Errorf("期望表名称: SDK测试表, 实际: %s", detail.Table.Name)
  207. }
  208. if len(detail.Fields) != 3 {
  209. t.Errorf("期望字段数: 3, 实际: %d", len(detail.Fields))
  210. }
  211. t.Logf("使用SDK查询表详情成功: %s, 表名称: %s", tableID, detail.Table.Name)
  212. }
  213. // listTablesWithSDK 使用SDK查询数据库表字典列表
  214. func listTablesWithSDK(t *testing.T, ctx context.Context, client *configure.Client) {
  215. query := &configure.DicTableQueryRequest{
  216. QueryRequest: queryreq.QueryRequest{
  217. Page: 0,
  218. PageSize: 10,
  219. },
  220. }
  221. result, err := client.ListTables(ctx, query)
  222. if err != nil {
  223. t.Fatalf("使用SDK查询表列表失败: %v", err)
  224. }
  225. if result.TotalCount < 0 {
  226. t.Errorf("总记录数应该 >= 0, 实际: %d", result.TotalCount)
  227. }
  228. t.Logf("使用SDK查询表列表成功: 总记录数 %d, 最后页 %d", result.TotalCount, result.LastPage)
  229. }
  230. // deleteTableWithSDK 使用SDK删除数据库表字典
  231. func deleteTableWithSDK(t *testing.T, ctx context.Context, client *configure.Client, tableID string) {
  232. err := client.DeleteTable(ctx, tableID)
  233. if err != nil {
  234. t.Fatalf("使用SDK删除表失败: %v", err)
  235. }
  236. t.Logf("使用SDK删除表成功: %s", tableID)
  237. }
  238. // verifyTableDeletedWithSDK 使用SDK验证数据库表字典已删除
  239. func verifyTableDeletedWithSDK(t *testing.T, ctx context.Context, client *configure.Client, tableID string) {
  240. _, err := client.GetTable(ctx, tableID)
  241. if err == nil {
  242. t.Errorf("期望表 %s 已被删除,但查询成功", tableID)
  243. } else {
  244. // 检查错误是否为"未找到"
  245. if err.Error() != "not found" && !contains(err.Error(), "不存在") {
  246. t.Logf("表删除验证: %v", err)
  247. }
  248. t.Logf("表 %s 已成功删除(查询返回错误)", tableID)
  249. }
  250. }
  251. // contains 检查字符串是否包含子串
  252. func contains(s, substr string) bool {
  253. return len(s) >= len(substr) && (s == substr || (len(s) > 0 && len(substr) > 0 && (s[0:len(substr)] == substr || contains(s[1:], substr))))
  254. }