package main import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "os/exec" "testing" "time" "git.x2erp.com/qdy/go-base/model/request/configreq" "git.x2erp.com/qdy/go-base/model/request/queryreq" "git.x2erp.com/qdy/go-base/sdk/configure" ) // TestSDKTokenAuth 测试SDK使用Token认证进行数据库表字典操作 func TestSDKTokenAuth(t *testing.T) { // 清除测试缓存 cmd := exec.Command("go", "clean", "-testcache") if err := cmd.Run(); err != nil { t.Logf("清除测试缓存失败: %v", err) // 继续执行测试 } // 1. 获取用户认证token authToken, err := getUserAuthToken(t) if err != nil { t.Fatalf("获取用户认证token失败: %v", err) } t.Logf("获取到用户认证token: %s...", authToken[:50]) // 2. 使用认证token创建配置token configToken, err := createConfigToken(t, authToken) if err != nil { t.Fatalf("创建配置token失败: %v", err) } t.Logf("获取到配置token: %s...", configToken[:50]) // 3. 使用配置token创建SDK客户端 client, err := configure.NewTokenAuthClient("http://localhost:8080", configToken) if err != nil { t.Fatalf("创建SDK客户端失败: %v", err) } t.Log("SDK客户端创建成功") // 4. 测试SDK功能 testTableID := fmt.Sprintf("test_sdk_table_%d", time.Now().Unix()) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() // 4.1 创建数据库表字典 t.Run("CreateTableWithSDK", func(t *testing.T) { createTableWithSDK(t, ctx, client, testTableID) }) // 4.2 查询数据库表字典详情 t.Run("GetTableWithSDK", func(t *testing.T) { getTableWithSDK(t, ctx, client, testTableID) }) // 4.3 查询数据库表字典列表 t.Run("ListTablesWithSDK", func(t *testing.T) { listTablesWithSDK(t, ctx, client) }) // 4.4 删除数据库表字典 t.Run("DeleteTableWithSDK", func(t *testing.T) { deleteTableWithSDK(t, ctx, client, testTableID) }) // 4.5 验证数据库表字典已删除 t.Run("VerifyTableDeletedWithSDK", func(t *testing.T) { verifyTableDeletedWithSDK(t, ctx, client, testTableID) }) t.Log("SDK Token认证测试全部通过") } // getUserAuthToken 获取用户认证token func getUserAuthToken(t *testing.T) (string, error) { httpClient := &http.Client{} // 用户登录 loginURL := "http://localhost:8080/api/login/user" loginData := map[string]string{ "user_id": "test-user-001", "password": "password123", } loginJSON, _ := json.Marshal(loginData) loginReq, err := http.NewRequest("POST", loginURL, bytes.NewReader(loginJSON)) if err != nil { return "", fmt.Errorf("创建登录请求失败: %w", err) } loginReq.Header.Set("Content-Type", "application/json") loginResp, err := httpClient.Do(loginReq) if err != nil { return "", fmt.Errorf("发送登录请求失败: %w", err) } defer loginResp.Body.Close() loginBody, err := io.ReadAll(loginResp.Body) if err != nil { return "", fmt.Errorf("读取登录响应失败: %w", err) } var loginResult map[string]interface{} if err := json.Unmarshal(loginBody, &loginResult); err != nil { return "", fmt.Errorf("解析登录响应失败: %w", err) } if !loginResult["success"].(bool) { return "", fmt.Errorf("登录失败: %v", loginResult) } return loginResult["data"].(string), nil } // createConfigToken 创建配置token func createConfigToken(t *testing.T, authToken string) (string, error) { httpClient := &http.Client{} // 使用认证token创建配置token url := "http://localhost:8080/api/create/config/token" data := configreq.ConfigTokenRequest{ ProjectID: "test-project", ServiceName: "test-service", ExpiresDays: 30, } jsonData, err := json.Marshal(data) if err != nil { return "", fmt.Errorf("JSON序列化失败: %w", err) } req, err := http.NewRequest("POST", url, bytes.NewReader(jsonData)) if err != nil { return "", fmt.Errorf("创建请求失败: %w", err) } // Token Auth 认证 req.Header.Set("Authorization", "Bearer "+authToken) req.Header.Set("Content-Type", "application/json") resp, err := httpClient.Do(req) if err != nil { return "", fmt.Errorf("发送请求失败: %w", err) } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return "", fmt.Errorf("读取响应失败: %w", err) } var result map[string]interface{} if err := json.Unmarshal(body, &result); err != nil { return "", fmt.Errorf("解析响应失败: %w", err) } if resp.StatusCode != 200 { return "", fmt.Errorf("期望状态码200,实际: %d", resp.StatusCode) } if !result["success"].(bool) { return "", fmt.Errorf("创建配置token失败: %v", result) } if data, ok := result["data"].(string); !ok || data == "" { return "", fmt.Errorf("未返回有效的配置token") } else { return data, nil } } // createTableWithSDK 使用SDK创建数据库表字典 func createTableWithSDK(t *testing.T, ctx context.Context, client *configure.Client, tableID string) { req := &configure.DicTableRequest{ TableID: tableID, TableType: "实体表", Name: "SDK测试表", Description: "使用SDK Token认证创建的测试表", Fields: []configure.DicTableFieldRequest{ { FieldID: tableID + ".id", TableID: tableID, FiledType: "实际字段", DataType: "数值型", FieldName: "id", FieldNameCN: "主键ID", Description: "主键字段", }, { FieldID: tableID + ".name", TableID: tableID, FiledType: "实际字段", DataType: "字符型", FieldName: "name", FieldNameCN: "名称", Description: "名称字段", }, { FieldID: tableID + ".created_at", TableID: tableID, FiledType: "实际字段", DataType: "日期型", FieldName: "created_at", FieldNameCN: "创建时间", Description: "创建时间字段", }, }, } detail, err := client.SaveTable(ctx, req) if err != nil { t.Fatalf("使用SDK创建表失败: %v", err) } if detail.Table.TableID != tableID { t.Errorf("期望表ID: %s, 实际: %s", tableID, detail.Table.TableID) } if len(detail.Fields) != 3 { t.Errorf("期望字段数: 3, 实际: %d", len(detail.Fields)) } t.Logf("使用SDK创建表成功: %s, 包含 %d 个字段", tableID, len(detail.Fields)) } // getTableWithSDK 使用SDK查询数据库表字典详情 func getTableWithSDK(t *testing.T, ctx context.Context, client *configure.Client, tableID string) { detail, err := client.GetTable(ctx, tableID) if err != nil { t.Fatalf("使用SDK查询表详情失败: %v", err) } if detail.Table.TableID != tableID { t.Errorf("期望表ID: %s, 实际: %s", tableID, detail.Table.TableID) } if detail.Table.Name != "SDK测试表" { t.Errorf("期望表名称: SDK测试表, 实际: %s", detail.Table.Name) } if len(detail.Fields) != 3 { t.Errorf("期望字段数: 3, 实际: %d", len(detail.Fields)) } t.Logf("使用SDK查询表详情成功: %s, 表名称: %s", tableID, detail.Table.Name) } // listTablesWithSDK 使用SDK查询数据库表字典列表 func listTablesWithSDK(t *testing.T, ctx context.Context, client *configure.Client) { query := &configure.DicTableQueryRequest{ QueryRequest: queryreq.QueryRequest{ Page: 0, PageSize: 10, }, } result, err := client.ListTables(ctx, query) if err != nil { t.Fatalf("使用SDK查询表列表失败: %v", err) } if result.TotalCount < 0 { t.Errorf("总记录数应该 >= 0, 实际: %d", result.TotalCount) } t.Logf("使用SDK查询表列表成功: 总记录数 %d, 最后页 %d", result.TotalCount, result.LastPage) } // deleteTableWithSDK 使用SDK删除数据库表字典 func deleteTableWithSDK(t *testing.T, ctx context.Context, client *configure.Client, tableID string) { err := client.DeleteTable(ctx, tableID) if err != nil { t.Fatalf("使用SDK删除表失败: %v", err) } t.Logf("使用SDK删除表成功: %s", tableID) } // verifyTableDeletedWithSDK 使用SDK验证数据库表字典已删除 func verifyTableDeletedWithSDK(t *testing.T, ctx context.Context, client *configure.Client, tableID string) { _, err := client.GetTable(ctx, tableID) if err == nil { t.Errorf("期望表 %s 已被删除,但查询成功", tableID) } else { // 检查错误是否为"未找到" if err.Error() != "not found" && !contains(err.Error(), "不存在") { t.Logf("表删除验证: %v", err) } t.Logf("表 %s 已成功删除(查询返回错误)", tableID) } } // contains 检查字符串是否包含子串 func contains(s, substr string) bool { return len(s) >= len(substr) && (s == substr || (len(s) > 0 && len(substr) > 0 && (s[0:len(substr)] == substr || contains(s[1:], substr)))) }