| package management |
|
|
| import ( |
| "bytes" |
| "encoding/json" |
| "net/http" |
| "net/http/httptest" |
| "os" |
| "path/filepath" |
| "sort" |
| "strings" |
| "testing" |
|
|
| "github.com/gin-gonic/gin" |
| "github.com/router-for-me/CLIProxyAPI/v6/internal/config" |
| "github.com/stretchr/testify/assert" |
| ) |
|
|
| |
| |
| func setupTestHandler(t *testing.T) (*Handler, *config.Config, func(), error) { |
| |
| tmpFile, err := os.CreateTemp("", "config_test_*.yaml") |
| if err != nil { |
| return nil, nil, nil, err |
| } |
|
|
| |
| if _, err := tmpFile.WriteString("{}\n"); err != nil { |
| tmpFile.Close() |
| os.Remove(tmpFile.Name()) |
| return nil, nil, nil, err |
| } |
| tmpFile.Close() |
|
|
| cfg := &config.Config{ |
| SDKConfig: config.SDKConfig{ |
| Access: config.AccessConfig{ |
| Providers: nil, |
| }, |
| }, |
| } |
|
|
| h := NewHandler(cfg, tmpFile.Name(), nil) |
|
|
| cleanup := func() { |
| os.Remove(tmpFile.Name()) |
| } |
|
|
| return h, cfg, cleanup, nil |
| } |
|
|
| func TestPutAPIKeys(t *testing.T) { |
| gin.SetMode(gin.TestMode) |
|
|
| h, cfg, cleanup, err := setupTestHandler(t) |
| assert.NoError(t, err) |
| defer cleanup() |
|
|
| |
| cfg.APIKeys = []string{"initial-key"} |
|
|
| |
| newKeys := []string{"key1", "key2", "key3"} |
| body, _ := json.Marshal(newKeys) |
|
|
| w := httptest.NewRecorder() |
| c, _ := gin.CreateTestContext(w) |
| c.Request, _ = http.NewRequest(http.MethodPut, "/api-keys", bytes.NewBuffer(body)) |
|
|
| h.PutAPIKeys(c) |
|
|
| assert.Equal(t, http.StatusOK, w.Code) |
|
|
| |
| assert.Equal(t, newKeys, cfg.APIKeys) |
|
|
| |
| assert.Nil(t, cfg.Access.Providers) |
|
|
| |
| wrapperBody := `{"items": ["wrapped-key-1", "wrapped-key-2"]}` |
| w = httptest.NewRecorder() |
| c, _ = gin.CreateTestContext(w) |
| c.Request, _ = http.NewRequest(http.MethodPut, "/api-keys", bytes.NewBufferString(wrapperBody)) |
|
|
| h.PutAPIKeys(c) |
|
|
| assert.Equal(t, http.StatusOK, w.Code) |
| assert.Equal(t, []string{"wrapped-key-1", "wrapped-key-2"}, cfg.APIKeys) |
| } |
|
|
| func TestDeleteAPIKeys(t *testing.T) { |
| gin.SetMode(gin.TestMode) |
|
|
| h, cfg, cleanup, err := setupTestHandler(t) |
| assert.NoError(t, err) |
| defer cleanup() |
|
|
| |
| cfg.APIKeys = []string{"key1", "key2", "key3", "key4"} |
|
|
| |
| w := httptest.NewRecorder() |
| c, _ := gin.CreateTestContext(w) |
| c.Request, _ = http.NewRequest(http.MethodDelete, "/api-keys?value=key2", nil) |
|
|
| h.DeleteAPIKeys(c) |
|
|
| assert.Equal(t, http.StatusOK, w.Code) |
| assert.Equal(t, []string{"key1", "key3", "key4"}, cfg.APIKeys) |
|
|
| |
| w = httptest.NewRecorder() |
| c, _ = gin.CreateTestContext(w) |
| c.Request, _ = http.NewRequest(http.MethodDelete, "/api-keys?index=1", nil) |
|
|
| h.DeleteAPIKeys(c) |
|
|
| assert.Equal(t, http.StatusOK, w.Code) |
| assert.Equal(t, []string{"key1", "key4"}, cfg.APIKeys) |
|
|
| |
| w = httptest.NewRecorder() |
| c, _ = gin.CreateTestContext(w) |
| c.Request, _ = http.NewRequest(http.MethodDelete, "/api-keys?value=non-existent", nil) |
|
|
| h.DeleteAPIKeys(c) |
|
|
| assert.Equal(t, http.StatusNotFound, w.Code) |
| assert.Equal(t, []string{"key1", "key4"}, cfg.APIKeys) |
|
|
| |
| w = httptest.NewRecorder() |
| c, _ = gin.CreateTestContext(w) |
| c.Request, _ = http.NewRequest(http.MethodDelete, "/api-keys?index=99", nil) |
|
|
| h.DeleteAPIKeys(c) |
|
|
| |
| |
| |
| assert.Equal(t, http.StatusBadRequest, w.Code) |
| assert.Equal(t, []string{"key1", "key4"}, cfg.APIKeys) |
| } |
|
|
| func TestGenericUpdateField(t *testing.T) { |
| gin.SetMode(gin.TestMode) |
|
|
| h, cfg, cleanup, err := setupTestHandler(t) |
| assert.NoError(t, err) |
| defer cleanup() |
|
|
| |
| cfg.Debug = false |
|
|
| body := `{"value": true}` |
| w := httptest.NewRecorder() |
| c, _ := gin.CreateTestContext(w) |
| c.Request, _ = http.NewRequest(http.MethodPut, "/debug", bytes.NewBufferString(body)) |
|
|
| |
| genericUpdateField(h, c, func(v bool) { |
| cfg.Debug = v |
| }) |
|
|
| assert.Equal(t, http.StatusOK, w.Code) |
| assert.True(t, cfg.Debug) |
|
|
| |
| loaded, err := config.LoadConfig(h.configFilePath) |
| assert.NoError(t, err) |
| assert.True(t, loaded.Debug) |
| } |
|
|
| func TestGenericListFiles(t *testing.T) { |
| gin.SetMode(gin.TestMode) |
|
|
| |
| tmpDir, err := os.MkdirTemp("", "test_files") |
| assert.NoError(t, err) |
| defer os.RemoveAll(tmpDir) |
|
|
| |
| _ = os.WriteFile(filepath.Join(tmpDir, "file1.txt"), []byte("content"), 0644) |
| _ = os.WriteFile(filepath.Join(tmpDir, "file2.json"), []byte("content"), 0644) |
| _ = os.WriteFile(filepath.Join(tmpDir, "file3.txt"), []byte("content"), 0644) |
|
|
| w := httptest.NewRecorder() |
| c, _ := gin.CreateTestContext(w) |
|
|
| genericListFiles(c, tmpDir, func(e os.DirEntry) (string, bool) { |
| if strings.HasSuffix(e.Name(), ".txt") { |
| return e.Name(), true |
| } |
| return "", false |
| }, func(files []string) { |
| |
| sort.Strings(files) |
| }) |
|
|
| assert.Equal(t, http.StatusOK, w.Code) |
|
|
| var resp struct { |
| Files []string `json:"files"` |
| } |
| err = json.Unmarshal(w.Body.Bytes(), &resp) |
| assert.NoError(t, err) |
| assert.Equal(t, []string{"file1.txt", "file3.txt"}, resp.Files) |
| } |
|
|